Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -1785,13 +1785,15 @@ FuncAttrs.addAttribute(llvm::Attribute::SpeculativeLoadHardening); } - if (getLangOpts().assumeFunctionsAreConvergent()) { - // Conservatively, mark all functions and calls in CUDA and OpenCL as - // convergent (meaning, they may call an intrinsically convergent op, such - // as __syncthreads() / barrier(), and so can't have certain optimizations - // applied around them). LLVM will remove this attribute where it safely - // can. - FuncAttrs.addAttribute(llvm::Attribute::Convergent); + if (!getLangOpts().assumeFunctionsAreConvergent()) { + // The language is assumed to not have SPMD semantics, so there should be no + // convergent operations anywhere in the program. + // + // Functions and calls in CUDA and OpenCL may be convergent (meaning, they + // may call an intrinsically convergent op, such as __syncthreads() / + // barrier(), and so can't have certain optimizations applied around them). + // LLVM will infer this attribute where it safely can. + FuncAttrs.addAttribute(llvm::Attribute::NoConvergent); } if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { @@ -1847,8 +1849,6 @@ FuncAttrs.addAttribute(llvm::Attribute::Cold); if (TargetDecl->hasAttr()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); - if (TargetDecl->hasAttr()) - FuncAttrs.addAttribute(llvm::Attribute::Convergent); if (const FunctionDecl *Fn = dyn_cast(TargetDecl)) { AddAttributesFromFunctionProtoType( Index: clang/lib/CodeGen/CGObjCMac.cpp =================================================================== --- clang/lib/CodeGen/CGObjCMac.cpp +++ clang/lib/CodeGen/CGObjCMac.cpp @@ -4256,6 +4256,7 @@ assert(!Locals.empty()); llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals); call->setDoesNotThrow(); + call->setNoConvergent(); call->setCallingConv(CGF.getRuntimeCC()); } Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -1940,13 +1940,13 @@ llvm::ConstantAsMetadata::get(Loc))); } - if (CGF.getLangOpts().assumeFunctionsAreConvergent()) + if (!CGF.getLangOpts().assumeFunctionsAreConvergent()) // Conservatively, mark all inline asm blocks in CUDA or OpenCL as // convergent (meaning, they may call an intrinsically convergent op, such // as bar.sync, and so can't have certain optimizations applied around // them). Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::Convergent); + llvm::Attribute::NoConvergent); // Extract all of the register value results from the asm. if (ResultRegTypes.size() == 1) { RegResults.push_back(&Result); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -3334,10 +3334,10 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, llvm::AttributeList ExtraAttrs, bool Local, bool AssumeConvergent) { - if (AssumeConvergent) { + if (!AssumeConvergent) { ExtraAttrs = ExtraAttrs.addAttribute(VMContext, llvm::AttributeList::FunctionIndex, - llvm::Attribute::Convergent); + llvm::Attribute::NoConvergent); } llvm::Constant *C = Index: clang/test/CXX/except/except.spec/p14-ir.cpp =================================================================== --- clang/test/CXX/except/except.spec/p14-ir.cpp +++ clang/test/CXX/except/except.spec/p14-ir.cpp @@ -78,4 +78,4 @@ // CHECK: ret void } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent nounwind{{.*}} } Index: clang/test/CXX/special/class.dtor/p3-0x.cpp =================================================================== --- clang/test/CXX/special/class.dtor/p3-0x.cpp +++ clang/test/CXX/special/class.dtor/p3-0x.cpp @@ -176,4 +176,4 @@ template TVC::~TVC() {} -// CHECK: attributes [[ATTRGRP]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[ATTRGRP]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/2008-04-08-NoExceptions.c =================================================================== --- clang/test/CodeGen/2008-04-08-NoExceptions.c +++ clang/test/CodeGen/2008-04-08-NoExceptions.c @@ -9,4 +9,4 @@ // CHECK-NOT: declare void @f() [[NUW]] -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/aarch64-tme.cpp =================================================================== --- clang/test/CodeGen/aarch64-tme.cpp +++ clang/test/CodeGen/aarch64-tme.cpp @@ -38,5 +38,5 @@ #endif // CHECK: define void @arm_feature_tme_defined() -// CHECK: attributes #1 = { nounwind } +// CHECK: attributes #1 = { noconvergent nounwind } Index: clang/test/CodeGen/address-safety-attr-flavors.cpp =================================================================== --- clang/test/CodeGen/address-safety-attr-flavors.cpp +++ clang/test/CodeGen/address-safety-attr-flavors.cpp @@ -25,51 +25,51 @@ // RUN: FileCheck -check-prefix=CHECK-KHWASAN %s int HasSanitizeAddress() { return 1; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address -// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address -// CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress -// CHECK-KHWASAN: Function Attrs: noinline nounwind sanitize_hwaddress +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: Function Attrs: noconvergent noinline nounwind sanitize_address +// CHECK-KASAN: Function Attrs: noconvergent noinline nounwind sanitize_address +// CHECK-HWASAN: Function Attrs: noconvergent noinline nounwind sanitize_hwaddress +// CHECK-KHWASAN: Function Attrs: noconvergent noinline nounwind sanitize_hwaddress __attribute__((no_sanitize("address"))) int NoSanitizeQuoteAddress() { return 0; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-KASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} -// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-KASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-HWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize_address)) int NoSanitizeAddress() { return 0; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-KASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} -// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-KASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-HWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize("kernel-address"))) int NoSanitizeKernelAddress() { return 0; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-KASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} -// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}} +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-KASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-HWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} +// CHECK-KHWASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_hwaddress$}} __attribute__((no_sanitize("hwaddress"))) int NoSanitizeHWAddress() { return 0; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}} -// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}} -// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}} +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_address$}} +// CHECK-KASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_address$}} +// CHECK-HWASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-KHWASAN: {{Function Attrs: noconvergent noinline nounwind$}} __attribute__((no_sanitize("kernel-hwaddress"))) int NoSanitizeKernelHWAddress() { return 0; } -// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}} -// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}} -// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}} -// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}} +// CHECK-NOASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-ASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_address$}} +// CHECK-KASAN: {{Function Attrs: noconvergent noinline nounwind sanitize_address$}} +// CHECK-HWASAN: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-KHWASAN: {{Function Attrs: noconvergent noinline nounwind$}} Index: clang/test/CodeGen/address-safety-attr.cpp =================================================================== --- clang/test/CodeGen/address-safety-attr.cpp +++ clang/test/CodeGen/address-safety-attr.cpp @@ -143,13 +143,13 @@ // BLFUNC: @__cxx_global_var_init{{.*}}[[WITH]] // ASAN: @__cxx_global_var_init{{.*}}[[WITH]] -// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// WITHOUT: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } -// BLFILE: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} } -// BLFILE: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// BLFILE: attributes [[WITH]] = { noconvergent noinline nounwind sanitize_address{{.*}} } +// BLFILE: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } -// BLFUNC: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} } -// BLFUNC: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// BLFUNC: attributes [[WITH]] = { noconvergent noinline nounwind sanitize_address{{.*}} } +// BLFUNC: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } -// ASAN: attributes [[WITH]] = { noinline nounwind sanitize_address{{.*}} } -// ASAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// ASAN: attributes [[WITH]] = { noconvergent noinline nounwind sanitize_address{{.*}} } +// ASAN: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/address-space-field1.c =================================================================== --- clang/test/CodeGen/address-space-field1.c +++ clang/test/CodeGen/address-space-field1.c @@ -5,17 +5,17 @@ // CHECK: [[p2addr:%.*]] = alloca %struct.S addrspace(2)* // CHECK: store %struct.S addrspace(1)* %p1, %struct.S addrspace(1)** [[p1addr]] // CHECK: store %struct.S addrspace(2)* %p2, %struct.S addrspace(2)** [[p2addr]] -// CHECK: [[t0:%.*]] = load %struct.S addrspace(2)*, %struct.S addrspace(2)** [[p2addr]], align 8 +// CHECK: [[t0:%.*]] = load %struct.S addrspace(2)*, %struct.S addrspace(2)** [[p2addr]], align 8 // CHECK: [[t1:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(2)* [[t0]], i32 0, i32 1 // CHECK: [[t2:%.*]] = load i32, i32 addrspace(2)* [[t1]], align 4 -// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)*, %struct.S addrspace(1)** [[p1addr]], align 8 -// CHECK: [[t4:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(1)* [[t3]], i32 0, i32 0 +// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)*, %struct.S addrspace(1)** [[p1addr]], align 8 +// CHECK: [[t4:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(1)* [[t3]], i32 0, i32 0 // CHECK: store i32 [[t2]], i32 addrspace(1)* [[t4]], align 4 -// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)*, %struct.S addrspace(2)** [[p2addr]], align 8 -// CHECK: [[t6:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(2)* [[t5]], i32 0, i32 0 -// CHECK: [[t7:%.*]] = load i32, i32 addrspace(2)* [[t6]], align 4 -// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)*, %struct.S addrspace(1)** [[p1addr]], align 8 -// CHECK: [[t9:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(1)* [[t8]], i32 0, i32 1 +// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)*, %struct.S addrspace(2)** [[p2addr]], align 8 +// CHECK: [[t6:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(2)* [[t5]], i32 0, i32 0 +// CHECK: [[t7:%.*]] = load i32, i32 addrspace(2)* [[t6]], align 4 +// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)*, %struct.S addrspace(1)** [[p1addr]], align 8 +// CHECK: [[t9:%.*]] = getelementptr inbounds %struct.S, %struct.S addrspace(1)* [[t8]], i32 0, i32 1 // CHECK: store i32 [[t7]], i32 addrspace(1)* [[t9]], align 4 // CHECK: ret void // CHECK:} @@ -37,4 +37,4 @@ p1->b = p2->a; } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/alias.c =================================================================== --- clang/test/CodeGen/alias.c +++ clang/test/CodeGen/alias.c @@ -78,9 +78,9 @@ // CHECKCC: call arm_aapcs_vfpcc i32 @inner_weak(i32 %{{.*}}) // CHECKCC: define internal arm_aapcs_vfpcc i32 @inner_weak(i32 %a) [[NUW]] { -// CHECKBASIC: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECKBASIC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } -// CHECKCC: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECKCC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } void test8_bar() {} void test8_foo() __attribute__((weak, alias("test8_bar"))); Index: clang/test/CodeGen/asm-attrs.c =================================================================== --- clang/test/CodeGen/asm-attrs.c +++ clang/test/CodeGen/asm-attrs.c @@ -10,9 +10,9 @@ // CHECK: call void asm sideeffect "foo7", {{.*}} [[NOATTRS]] // CHECK: call i32 asm "foo8", {{.*}} [[READNONE]] -// CHECK: attributes [[READNONE]] = { nounwind readnone } -// CHECK: attributes [[NOATTRS]] = { nounwind } -// CHECK: attributes [[READONLY]] = { nounwind readonly } +// CHECK: attributes [[READNONE]] = { noconvergent nounwind readnone } +// CHECK: attributes [[NOATTRS]] = { noconvergent nounwind } +// CHECK: attributes [[READONLY]] = { noconvergent nounwind readonly } int g0, g1; Index: clang/test/CodeGen/attr-naked.c =================================================================== --- clang/test/CodeGen/attr-naked.c +++ clang/test/CodeGen/attr-naked.c @@ -23,5 +23,5 @@ // CHECK: unreachable } -// CHECK: attributes [[NAKED_OPTNONE]] = { naked noinline nounwind optnone{{.*}} } -// CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } +// CHECK: attributes [[NAKED_OPTNONE]] = { naked noconvergent noinline nounwind optnone{{.*}} } +// CHECK: attributes [[NAKED]] = { naked noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/attributes.c =================================================================== --- clang/test/CodeGen/attributes.c +++ clang/test/CodeGen/attributes.c @@ -107,10 +107,10 @@ (*p)(); } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noconvergent noinline noreturn nounwind{{.*}} } // CHECK: attributes [[COLDDEF]] = { cold {{.*}}} // CHECK: attributes [[COLDDECL]] = { cold {{.*}}} // CHECK: attributes [[NOCF_CHECK_FUNC]] = { nocf_check {{.*}}} // CHECK: attributes [[COLDSITE]] = { cold {{.*}}} -// CHECK: attributes [[NOCF_CHECK_CALL]] = { nocf_check } +// CHECK: attributes [[NOCF_CHECK_CALL]] = { nocf_check noconvergent } Index: clang/test/CodeGen/builtin-attributes.c =================================================================== --- clang/test/CodeGen/builtin-attributes.c +++ clang/test/CodeGen/builtin-attributes.c @@ -58,4 +58,4 @@ return e; } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent nounwind{{.*}} } Index: clang/test/CodeGen/builtin-sqrt.c =================================================================== --- clang/test/CodeGen/builtin-sqrt.c +++ clang/test/CodeGen/builtin-sqrt.c @@ -11,5 +11,5 @@ // HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} readnone // NO_ERRNO: declare float @llvm.sqrt.f32(float) [[ATTR:#[0-9]+]] -// NO_ERRNO: attributes [[ATTR]] = { nounwind readnone {{.*}}} +// NO_ERRNO: attributes [[ATTR]] = { noconvergent nounwind readnone {{.*}}} Index: clang/test/CodeGen/complex-builtins.c =================================================================== --- clang/test/CodeGen/complex-builtins.c +++ clang/test/CodeGen/complex-builtins.c @@ -49,7 +49,7 @@ // HAS_ERRNO: declare <2 x float> @casinf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - __builtin_casinh(f); __builtin_casinhf(f); __builtin_casinhl(f); + __builtin_casinh(f); __builtin_casinhf(f); __builtin_casinhl(f); // NO__ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] @@ -58,7 +58,7 @@ // HAS_ERRNO: declare <2 x float> @casinhf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - __builtin_catan(f); __builtin_catanf(f); __builtin_catanl(f); + __builtin_catan(f); __builtin_catanf(f); __builtin_catanl(f); // NO__ERRNO: declare { double, double } @catan(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] @@ -126,7 +126,7 @@ // HAS_ERRNO: declare <2 x float> @clogf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - __builtin_cproj(f); __builtin_cprojf(f); __builtin_cprojl(f); + __builtin_cproj(f); __builtin_cprojf(f); __builtin_cprojl(f); // NO__ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] @@ -169,7 +169,7 @@ // HAS_ERRNO: declare <2 x float> @csinhf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - __builtin_csqrt(f); __builtin_csqrtf(f); __builtin_csqrtl(f); + __builtin_csqrt(f); __builtin_csqrtf(f); __builtin_csqrtl(f); // NO__ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] @@ -187,7 +187,7 @@ // HAS_ERRNO: declare <2 x float> @ctanf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - __builtin_ctanh(f); __builtin_ctanhf(f); __builtin_ctanhl(f); + __builtin_ctanh(f); __builtin_ctanhf(f); __builtin_ctanhl(f); // NO__ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] @@ -199,8 +199,8 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: clang/test/CodeGen/complex-libcalls.c =================================================================== --- clang/test/CodeGen/complex-libcalls.c +++ clang/test/CodeGen/complex-libcalls.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO // RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO -// Test attributes and builtin codegen of complex library calls. +// Test attributes and builtin codegen of complex library calls. void foo(float f) { cabs(f); cabsf(f); cabsl(f); @@ -49,7 +49,7 @@ // HAS_ERRNO: declare <2 x float> @casinf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - casinh(f); casinhf(f); casinhl(f); + casinh(f); casinhf(f); casinhl(f); // NO__ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] @@ -58,7 +58,7 @@ // HAS_ERRNO: declare <2 x float> @casinhf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - catan(f); catanf(f); catanl(f); + catan(f); catanf(f); catanl(f); // NO__ERRNO: declare { double, double } @catan(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] @@ -128,7 +128,7 @@ // HAS_ERRNO: declare <2 x float> @clogf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - cproj(f); cprojf(f); cprojl(f); + cproj(f); cprojf(f); cprojl(f); // NO__ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] @@ -171,7 +171,7 @@ // HAS_ERRNO: declare <2 x float> @csinhf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - csqrt(f); csqrtf(f); csqrtl(f); + csqrt(f); csqrtf(f); csqrtl(f); // NO__ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] @@ -189,7 +189,7 @@ // HAS_ERRNO: declare <2 x float> @ctanf(<2 x float>) [[NOT_READNONE]] // HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] - ctanh(f); ctanhf(f); ctanhl(f); + ctanh(f); ctanhf(f); ctanhl(f); // NO__ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] // NO__ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] @@ -201,8 +201,8 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: clang/test/CodeGen/convergent-functions.cpp =================================================================== --- clang/test/CodeGen/convergent-functions.cpp +++ clang/test/CodeGen/convergent-functions.cpp @@ -3,6 +3,28 @@ // Test that the -fconvergent-functions flag works -// CONVFUNC: attributes #0 = { convergent {{.*}} } -// NOCONVFUNC-NOT: convergent +// Everything may be convergent +// CONVFUNC-NOT: noconvergent void func() { } + +void extern_func(); + +void call_extern() { + extern_func(); +} + +void asm_func() { + __asm volatile(";foo"); +} + +void asm_decl() __asm("llvm.maybe.convergent"); +void call_asm_decl() { + asm_decl(); +} + +// All attribute contexts should have noconvergent here +// NOCONVFUNC: attributes #0 = { noconvergent +// NOCONVFUNC: attributes #1 = { noconvergent +// NOCONVFUNC: attributes #2 = { noconvergent +// NOCONVFUNC: attributes #3 = { noconvergent +// NOCONVFUNC-NOT: attributes Index: clang/test/CodeGen/exceptions-seh-finally.c =================================================================== --- clang/test/CodeGen/exceptions-seh-finally.c +++ clang/test/CodeGen/exceptions-seh-finally.c @@ -257,14 +257,14 @@ // CHECK: invoke void @might_crash( // CHECK: call void @"?fin$0@0@finally_within_finally@@"( -// CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) [ "funclet"( +// CHECK: call void @"?fin$0@0@finally_within_finally@@"({{.*}}) #{{[0-9]+}} [ "funclet"( // CHECK-LABEL: define internal void @"?fin$0@0@finally_within_finally@@"({{[^)]*}}) // CHECK-SAME: [[finally_attrs]] // CHECK: invoke void @might_crash( // CHECK: call void @"?fin$1@0@finally_within_finally@@"( -// CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) [ "funclet"( +// CHECK: call void @"?fin$1@0@finally_within_finally@@"({{.*}}) #{{[0-9]+}} [ "funclet"( // CHECK-LABEL: define internal void @"?fin$1@0@finally_within_finally@@"({{[^)]*}}) // CHECK-SAME: [[finally_attrs]] @@ -284,4 +284,4 @@ // Look for the absence of noinline. Enum attributes come first, so check that // a string attribute is the first to verify that no enum attributes are // present. -// CHECK: attributes [[finally_attrs]] = { "{{.*}}" } +// CHECK: attributes [[finally_attrs]] = { noconvergent "{{.*}}" } Index: clang/test/CodeGen/function-attributes.c =================================================================== --- clang/test/CodeGen/function-attributes.c +++ clang/test/CodeGen/function-attributes.c @@ -109,11 +109,11 @@ _setjmp(0); } -// CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} } -// CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} } -// CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} } -// CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } -// CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } -// CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } -// CHECK: attributes [[RT_CALL]] = { optsize returns_twice } +// CHECK: attributes [[NUW]] = { noconvergent nounwind optsize{{.*}} } +// CHECK: attributes [[AI]] = { alwaysinline noconvergent nounwind optsize{{.*}} } +// CHECK: attributes [[NUW_OS_RN]] = { noconvergent nounwind optsize readnone{{.*}} } +// CHECK: attributes [[SR]] = { noconvergent nounwind optsize{{.*}} "stackrealign"{{.*}} } +// CHECK: attributes [[RT]] = { noconvergent nounwind optsize returns_twice{{.*}} } +// CHECK: attributes [[NR]] = { noconvergent noreturn optsize } +// CHECK: attributes [[NUW_RN]] = { noconvergent nounwind optsize readnone } +// CHECK: attributes [[RT_CALL]] = { noconvergent optsize returns_twice } Index: clang/test/CodeGen/incomplete-function-type-2.c =================================================================== --- clang/test/CodeGen/incomplete-function-type-2.c +++ clang/test/CodeGen/incomplete-function-type-2.c @@ -16,4 +16,4 @@ p1(0.0); } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/libcall-declarations.c =================================================================== --- clang/test/CodeGen/libcall-declarations.c +++ clang/test/CodeGen/libcall-declarations.c @@ -614,8 +614,8 @@ // CHECK-ERRNO: declare { double, double } @ctanh(double, double) [[NONCONST]] // CHECK-ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[NONCONST]] -// CHECK-NOERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } -// CHECK-NOERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } +// CHECK-NOERRNO: attributes [[NUWRN]] = { noconvergent nounwind readnone{{.*}} } +// CHECK-NOERRNO: attributes [[NUWRO]] = { noconvergent nounwind readonly{{.*}} } -// CHECK-ERRNO: attributes [[NUWRN]] = { nounwind readnone{{.*}} } -// CHECK-ERRNO: attributes [[NUWRO]] = { nounwind readonly{{.*}} } +// CHECK-ERRNO: attributes [[NUWRN]] = { noconvergent nounwind readnone{{.*}} } +// CHECK-ERRNO: attributes [[NUWRO]] = { noconvergent nounwind readonly{{.*}} } Index: clang/test/CodeGen/libcalls-fno-builtin.c =================================================================== --- clang/test/CodeGen/libcalls-fno-builtin.c +++ clang/test/CodeGen/libcalls-fno-builtin.c @@ -160,4 +160,4 @@ // CHECK-LABEL: t26 // CHECK: call{{.*}}@fopen{{.*}} [[ATTR]] -// CHECK: [[ATTR]] = { nobuiltin } +// CHECK: [[ATTR]] = { nobuiltin noconvergent } Index: clang/test/CodeGen/libcalls.c =================================================================== --- clang/test/CodeGen/libcalls.c +++ clang/test/CodeGen/libcalls.c @@ -123,5 +123,5 @@ // CHECK-YES-NOT: declare float @logf(float) [[NUW_RN]] } -// CHECK-NO-DAG: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK-NO-DAG: attributes [[NUW_RNI]] = { nounwind readnone speculatable willreturn } +// CHECK-NO-DAG: attributes [[NUW_RN]] = { noconvergent nounwind readnone{{.*}} } +// CHECK-NO-DAG: attributes [[NUW_RNI]] = { noconvergent nounwind readnone speculatable willreturn } Index: clang/test/CodeGen/math-builtins.c =================================================================== --- clang/test/CodeGen/math-builtins.c +++ clang/test/CodeGen/math-builtins.c @@ -70,7 +70,7 @@ // HAS_ERRNO-NOT: .inf // HAS_ERRNO-NOT: @inf - __builtin_ldexp(f,f); __builtin_ldexpf(f,f); __builtin_ldexpl(f,f); + __builtin_ldexp(f,f); __builtin_ldexpf(f,f); __builtin_ldexpl(f,f); // NO__ERRNO: declare double @ldexp(double, i32) [[READNONE]] // NO__ERRNO: declare float @ldexpf(float, i32) [[READNONE]] @@ -79,7 +79,7 @@ // HAS_ERRNO: declare float @ldexpf(float, i32) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOT_READNONE]] - __builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); + __builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); // NO__ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] // NO__ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] @@ -138,7 +138,7 @@ // HAS_ERRNO: declare float @acosf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[NOT_READNONE]] - __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); + __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); // NO__ERRNO: declare double @acosh(double) [[READNONE]] // NO__ERRNO: declare float @acoshf(float) [[READNONE]] @@ -147,7 +147,7 @@ // HAS_ERRNO: declare float @acoshf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NOT_READNONE]] - __builtin_asin(f); __builtin_asinf(f); __builtin_asinl(f); + __builtin_asin(f); __builtin_asinf(f); __builtin_asinl(f); // NO__ERRNO: declare double @asin(double) [[READNONE]] // NO__ERRNO: declare float @asinf(float) [[READNONE]] @@ -174,7 +174,7 @@ // HAS_ERRNO: declare float @atanf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[NOT_READNONE]] - __builtin_atanh(f); __builtin_atanhf(f); __builtin_atanhl(f); + __builtin_atanh(f); __builtin_atanhf(f); __builtin_atanhl(f); // NO__ERRNO: declare double @atanh(double) [[READNONE]] // NO__ERRNO: declare float @atanhf(float) [[READNONE]] @@ -201,7 +201,7 @@ // HAS_ERRNO: declare float @llvm.ceil.f32(float) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare x86_fp80 @llvm.ceil.f80(x86_fp80) [[READNONE_INTRINSIC]] - __builtin_cos(f); __builtin_cosf(f); __builtin_cosl(f); + __builtin_cos(f); __builtin_cosf(f); __builtin_cosl(f); // NO__ERRNO: declare double @llvm.cos.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.cos.f32(float) [[READNONE_INTRINSIC]] @@ -246,7 +246,7 @@ // HAS_ERRNO: declare float @expf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[NOT_READNONE]] - __builtin_exp2(f); __builtin_exp2f(f); __builtin_exp2l(f); + __builtin_exp2(f); __builtin_exp2f(f); __builtin_exp2l(f); // NO__ERRNO: declare double @llvm.exp2.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.exp2.f32(float) [[READNONE_INTRINSIC]] @@ -333,7 +333,7 @@ // HAS_ERRNO: declare float @hypotf(float, float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NOT_READNONE]] - __builtin_ilogb(f); __builtin_ilogbf(f); __builtin_ilogbl(f); + __builtin_ilogb(f); __builtin_ilogbf(f); __builtin_ilogbl(f); // NO__ERRNO: declare i32 @ilogb(double) [[READNONE]] // NO__ERRNO: declare i32 @ilogbf(float) [[READNONE]] @@ -531,7 +531,7 @@ // HAS_ERRNO: declare float @sinhf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NOT_READNONE]] - __builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); + __builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); // NO__ERRNO: declare double @llvm.sqrt.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.sqrt.f32(float) [[READNONE_INTRINSIC]] @@ -580,10 +580,10 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: clang/test/CodeGen/math-libcalls.c =================================================================== --- clang/test/CodeGen/math-libcalls.c +++ clang/test/CodeGen/math-libcalls.c @@ -51,7 +51,7 @@ // HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] - ldexp(f,f); ldexpf(f,f); ldexpl(f,f); + ldexp(f,f); ldexpf(f,f); ldexpl(f,f); // NO__ERRNO: declare double @ldexp(double, i32) [[READNONE]] // NO__ERRNO: declare float @ldexpf(float, i32) [[READNONE]] @@ -60,7 +60,7 @@ // HAS_ERRNO: declare float @ldexpf(float, i32) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOT_READNONE]] - modf(f,d); modff(f,fp); modfl(f,l); + modf(f,d); modff(f,fp); modfl(f,l); // NO__ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] // NO__ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] @@ -69,7 +69,7 @@ // HAS_ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] - nan(c); nanf(c); nanl(c); + nan(c); nanf(c); nanl(c); // NO__ERRNO: declare double @nan(i8*) [[READONLY:#[0-9]+]] // NO__ERRNO: declare float @nanf(i8*) [[READONLY]] @@ -97,7 +97,7 @@ // HAS_ERRNO: declare float @acosf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[NOT_READNONE]] - acosh(f); acoshf(f); acoshl(f); + acosh(f); acoshf(f); acoshl(f); // NO__ERRNO: declare double @acosh(double) [[READNONE]] // NO__ERRNO: declare float @acoshf(float) [[READNONE]] @@ -106,7 +106,7 @@ // HAS_ERRNO: declare float @acoshf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NOT_READNONE]] - asin(f); asinf(f); asinl(f); + asin(f); asinf(f); asinl(f); // NO__ERRNO: declare double @asin(double) [[READNONE]] // NO__ERRNO: declare float @asinf(float) [[READNONE]] @@ -133,7 +133,7 @@ // HAS_ERRNO: declare float @atanf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[NOT_READNONE]] - atanh(f); atanhf(f); atanhl(f); + atanh(f); atanhf(f); atanhl(f); // NO__ERRNO: declare double @atanh(double) [[READNONE]] // NO__ERRNO: declare float @atanhf(float) [[READNONE]] @@ -160,7 +160,7 @@ // HAS_ERRNO: declare float @llvm.ceil.f32(float) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare x86_fp80 @llvm.ceil.f80(x86_fp80) [[READNONE_INTRINSIC]] - cos(f); cosf(f); cosl(f); + cos(f); cosf(f); cosl(f); // NO__ERRNO: declare double @llvm.cos.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.cos.f32(float) [[READNONE_INTRINSIC]] @@ -205,7 +205,7 @@ // HAS_ERRNO: declare float @expf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[NOT_READNONE]] - exp2(f); exp2f(f); exp2l(f); + exp2(f); exp2f(f); exp2l(f); // NO__ERRNO: declare double @llvm.exp2.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.exp2.f32(float) [[READNONE_INTRINSIC]] @@ -288,7 +288,7 @@ // HAS_ERRNO: declare float @hypotf(float, float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NOT_READNONE]] - ilogb(f); ilogbf(f); ilogbl(f); + ilogb(f); ilogbf(f); ilogbl(f); // NO__ERRNO: declare i32 @ilogb(double) [[READNONE]] // NO__ERRNO: declare i32 @ilogbf(float) [[READNONE]] @@ -486,7 +486,7 @@ // HAS_ERRNO: declare float @sinhf(float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NOT_READNONE]] - sqrt(f); sqrtf(f); sqrtl(f); + sqrt(f); sqrtf(f); sqrtl(f); // NO__ERRNO: declare double @llvm.sqrt.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.sqrt.f32(float) [[READNONE_INTRINSIC]] @@ -535,10 +535,10 @@ // NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } -// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // NO__ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } -// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { noconvergent nounwind "correctly{{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } Index: clang/test/CodeGen/memtag-attr.cpp =================================================================== --- clang/test/CodeGen/memtag-attr.cpp +++ clang/test/CodeGen/memtag-attr.cpp @@ -9,11 +9,11 @@ // RUN: FileCheck -check-prefix=CHECK-MEMTAG %s int HasSanitizeMemTag() { return 1; } -// CHECK-NO: {{Function Attrs: noinline nounwind$}} -// CHECK-MEMTAG: Function Attrs: noinline nounwind sanitize_memtag +// CHECK-NO: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-MEMTAG: Function Attrs: noconvergent noinline nounwind sanitize_memtag __attribute__((no_sanitize("memtag"))) int NoSanitizeQuoteAddress() { return 0; } -// CHECK-NO: {{Function Attrs: noinline nounwind$}} -// CHECK-MEMTAG: {{Function Attrs: noinline nounwind$}} +// CHECK-NO: {{Function Attrs: noconvergent noinline nounwind$}} +// CHECK-MEMTAG: {{Function Attrs: noconvergent noinline nounwind$}} Index: clang/test/CodeGen/micromips-attr.c =================================================================== --- clang/test/CodeGen/micromips-attr.c +++ clang/test/CodeGen/micromips-attr.c @@ -8,5 +8,5 @@ // CHECK: define void @nofoo() [[NOMICROMIPS:#[0-9]+]] -// CHECK: attributes [[MICROMIPS]] = { noinline nounwind {{.*}} "micromips" {{.*}} } -// CHECK: attributes [[NOMICROMIPS]] = { noinline nounwind {{.*}} "nomicromips" {{.*}} } +// CHECK: attributes [[MICROMIPS]] = { {{.*}} noinline nounwind {{.*}} "micromips" {{.*}} } +// CHECK: attributes [[NOMICROMIPS]] = { {{.*}} nounwind {{.*}} "nomicromips" {{.*}} } Index: clang/test/CodeGen/mips-constraint-regs.c =================================================================== --- clang/test/CodeGen/mips-constraint-regs.c +++ clang/test/CodeGen/mips-constraint-regs.c @@ -46,4 +46,4 @@ return 0; } -// CHECK: attributes [[NUW]] = { nounwind } +// CHECK: attributes [[NUW]] = { noconvergent nounwind } Index: clang/test/CodeGen/mips-vector-arg.c =================================================================== --- clang/test/CodeGen/mips-vector-arg.c +++ clang/test/CodeGen/mips-vector-arg.c @@ -26,6 +26,6 @@ test_v4i32_2(a3, a2, a1); } -// O32: attributes [[NUW]] = { nounwind{{.*}} } +// O32: attributes [[NUW]] = { noconvergent nounwind{{.*}} } -// N64: attributes [[NUW]] = { nounwind{{.*}} } +// N64: attributes [[NUW]] = { noconvergent nounwind{{.*}} } Index: clang/test/CodeGen/mips16-attr.c =================================================================== --- clang/test/CodeGen/mips16-attr.c +++ clang/test/CodeGen/mips16-attr.c @@ -11,7 +11,7 @@ // CHECK: define void @nofoo() [[NOMIPS16:#[0-9]+]] -// CHECK: attributes [[MIPS16]] = { noinline nounwind {{.*}} "mips16" {{.*}} } +// CHECK: attributes [[MIPS16]] = { noconvergent noinline nounwind {{.*}} "mips16" {{.*}} } -// CHECK: attributes [[NOMIPS16]] = { noinline nounwind {{.*}} "nomips16" {{.*}} } +// CHECK: attributes [[NOMIPS16]] = { noconvergent noinline nounwind {{.*}} "nomips16" {{.*}} } Index: clang/test/CodeGen/mrtd.c =================================================================== --- clang/test/CodeGen/mrtd.c +++ clang/test/CodeGen/mrtd.c @@ -25,4 +25,4 @@ // CHECK-LABEL: define x86_stdcallcc void @quux // CHECK: call void (i32, ...) @qux -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/ms-declspecs.c =================================================================== --- clang/test/CodeGen/ms-declspecs.c +++ clang/test/CodeGen/ms-declspecs.c @@ -37,8 +37,8 @@ // CHECK: call void @noalias_callee({{.*}}) [[NA:#[0-9]+]] void noalias_caller(int *x) { noalias_callee(x); } -// CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} } -// CHECK: attributes [[NUW]] = { nounwind{{.*}} } -// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[NR]] = { noreturn } -// CHECK: attributes [[NA]] = { argmemonly nounwind{{.*}} } +// CHECK: attributes [[NAKED]] = { naked noconvergent noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent nounwind{{.*}} } +// CHECK: attributes [[NI]] = { noconvergent noinline nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noconvergent noreturn } +// CHECK: attributes [[NA]] = { argmemonly noconvergent nounwind{{.*}} } Index: clang/test/CodeGen/noduplicate-cxx11-test.cpp =================================================================== --- clang/test/CodeGen/noduplicate-cxx11-test.cpp +++ clang/test/CodeGen/noduplicate-cxx11-test.cpp @@ -17,4 +17,4 @@ } -// CHECK: attributes [[NI]] = { noduplicate {{.*}}nounwind{{.*}} } +// CHECK: attributes [[NI]] = { noconvergent noduplicate {{.*}}nounwind{{.*}} } Index: clang/test/CodeGen/noinline.c =================================================================== --- clang/test/CodeGen/noinline.c +++ clang/test/CodeGen/noinline.c @@ -12,10 +12,10 @@ // NOINLINE: @foo // NOINLINE: dont_inline_me // NOINLINE-NOT: inlinehint - pa[0] = dont_inline_me(pa[1],pa[2]); + pa[0] = dont_inline_me(pa[1],pa[2]); // NOINLINE-NOT: inline_me pa[3] = inline_me(pa[4],pa[5]); } -// NOINLINE: Function Attrs: noinline +// NOINLINE: Function Attrs: noconvergent noinline // NOINLINE: @dont_inline_me Index: clang/test/CodeGen/noplt.c =================================================================== --- clang/test/CodeGen/noplt.c +++ clang/test/CodeGen/noplt.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -fno-plt %s -o - | FileCheck %s -check-prefix=CHECK-NOPLT -check-prefix=CHECK-NOPLT-METADATA -// CHECK-NOPLT: Function Attrs: nonlazybind +// CHECK-NOPLT: Function Attrs: noconvergent nonlazybind // CHECK-NOPLT-NEXT: declare {{.*}}i32 @foo // CHECK-NOPLT-METADATA: !"RtLibUseGOT" int foo(); Index: clang/test/CodeGen/ppc64-complex-parms.c =================================================================== --- clang/test/CodeGen/ppc64-complex-parms.c +++ clang/test/CodeGen/ppc64-complex-parms.c @@ -180,4 +180,4 @@ // CHECK: %[[VAR77:[A-Za-z0-9.]+]] = load i64, i64* %[[VAR76]], align 8 // CHECK: %{{[A-Za-z0-9.]+}} = call i64 @foo_long_long(i64 %[[VAR75]], i64 %[[VAR77]]) -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/ppc64-complex-return.c =================================================================== --- clang/test/CodeGen/ppc64-complex-return.c +++ clang/test/CodeGen/ppc64-complex-return.c @@ -126,4 +126,4 @@ // CHECK: extractvalue { i64, i64 } [[VAR8]], 1 -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/ppc64-extend.c =================================================================== --- clang/test/CodeGen/ppc64-extend.c +++ clang/test/CodeGen/ppc64-extend.c @@ -13,4 +13,4 @@ unsigned int f4(void) { return 0; } // CHECK: define zeroext i32 @f4() [[NUW]] -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGen/pragma-weak.c =================================================================== --- clang/test/CodeGen/pragma-weak.c +++ clang/test/CodeGen/pragma-weak.c @@ -188,5 +188,5 @@ int correct_linkage; -// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[RN]] = { noinline nounwind optnone readnone{{.*}} } +// CHECK: attributes [[NI]] = { noconvergent noinline nounwind{{.*}} } +// CHECK: attributes [[RN]] = { noconvergent noinline nounwind optnone readnone{{.*}} } Index: clang/test/CodeGen/sanitize-thread-attr.cpp =================================================================== --- clang/test/CodeGen/sanitize-thread-attr.cpp +++ clang/test/CodeGen/sanitize-thread-attr.cpp @@ -54,9 +54,9 @@ // BL: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]] // TSAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]] -// WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// WITHOUT: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } -// BL: attributes [[NOATTR]] = { noinline nounwind{{.*}} } +// BL: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } -// TSAN: attributes [[NOATTR]] = { noinline nounwind{{.*}} } -// TSAN: attributes [[WITH]] = { noinline nounwind sanitize_thread{{.*}} } +// TSAN: attributes [[NOATTR]] = { noconvergent noinline nounwind{{.*}} } +// TSAN: attributes [[WITH]] = { noconvergent noinline nounwind sanitize_thread{{.*}} } Index: clang/test/CodeGen/sanitize-thread-no-checking-at-run-time.m =================================================================== --- clang/test/CodeGen/sanitize-thread-no-checking-at-run-time.m +++ clang/test/CodeGen/sanitize-thread-no-checking-at-run-time.m @@ -38,4 +38,4 @@ // TSAN: define linkonce_odr hidden void @__destroy_helper_block_8_32o(i8* %0) unnamed_addr [[ATTR:#[0-9]+]] } -// TSAN: attributes [[ATTR]] = { noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} } +// TSAN: attributes [[ATTR]] = { noconvergent noinline nounwind {{.*}} "sanitize_thread_no_checking_at_run_time" {{.*}} } Index: clang/test/CodeGen/stackrealign-main.c =================================================================== --- clang/test/CodeGen/stackrealign-main.c +++ clang/test/CodeGen/stackrealign-main.c @@ -13,7 +13,7 @@ return 0; } -// CHECK: attributes [[OTHER]] = { noinline nounwind optnone +// CHECK: attributes [[OTHER]] = { noconvergent noinline nounwind optnone // CHECK-NOT: "stackrealign" // CHECK: } -// CHECK: attributes [[MAIN]] = { noinline nounwind optnone {{.*}}"stackrealign"{{.*}} } +// CHECK: attributes [[MAIN]] = { noconvergent noinline nounwind optnone {{.*}}"stackrealign"{{.*}} } Index: clang/test/CodeGen/struct-passing.c =================================================================== --- clang/test/CodeGen/struct-passing.c +++ clang/test/CodeGen/struct-passing.c @@ -23,5 +23,5 @@ // CHECK: declare void @f4({{.*}} byval({{.*}}) align 4) // CHECK: declare void @f5({{.*}} byval({{.*}}) align 4) -// CHECK: attributes [[RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[RN]] = { noconvergent nounwind readnone{{.*}} } +// CHECK: attributes [[RO]] = { noconvergent nounwind readonly{{.*}} } Index: clang/test/CodeGen/unwind-attr.c =================================================================== --- clang/test/CodeGen/unwind-attr.c +++ clang/test/CodeGen/unwind-attr.c @@ -23,7 +23,7 @@ return 0; } -// CHECK: attributes [[TF]] = { noinline optnone "{{.*}} } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[TF]] = { noconvergent noinline optnone "{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } -// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK-NOEXC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu =================================================================== --- clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu +++ clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu @@ -31,7 +31,7 @@ // NAMD-NOT: "amdgpu-num-vgpr" // NAMD-NOT: "amdgpu-num-sgpr" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" -// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-num-sgpr"="32" -// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" +// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { noinline nounwind optnone "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-num-vgpr"="64" Index: clang/test/CodeGenCUDA/convergent.cu =================================================================== --- clang/test/CodeGenCUDA/convergent.cu +++ clang/test/CodeGenCUDA/convergent.cu @@ -10,16 +10,14 @@ #include "Inputs/cuda.h" -// DEVICE: Function Attrs: -// DEVICE-SAME: convergent +// DEVICE: Function Attrs: noinline nounwind optnone{{$}} // DEVICE-NEXT: define void @_Z3foov __device__ void foo() {} -// HOST: Function Attrs: -// HOST-NOT: convergent +// HOST: Function Attrs: noconvergent noinline nounwind optnone{{$}} // HOST-NEXT: define void @_Z3barv -// DEVICE: Function Attrs: -// DEVICE-SAME: convergent + +// DEVICE: Function Attrs: noinline nounwind optnone{{$}} // DEVICE-NEXT: define void @_Z3barv __host__ __device__ void baz(); __host__ __device__ void bar() { @@ -33,13 +31,9 @@ } // DEVICE: declare void @_Z3bazv() [[BAZ_ATTR:#[0-9]+]] -// DEVICE: attributes [[BAZ_ATTR]] = { -// DEVICE-SAME: convergent -// DEVICE-SAME: } -// DEVICE-DAG: attributes [[CALL_ATTR]] = { convergent -// DEVICE-DAG: attributes [[ASM_ATTR]] = { convergent + +// No noconvergent +// DEVICE: attributes [[BAZ_ATTR]] = { nounwind "{{.*}} } // HOST: declare void @_Z3bazv() [[BAZ_ATTR:#[0-9]+]] -// HOST: attributes [[BAZ_ATTR]] = { -// HOST-NOT: convergent -// NOST-SAME: } +// HOST: attributes [[BAZ_ATTR]] = { {{.*}}noconvergent{{.*}} } Index: clang/test/CodeGenCUDA/propagate-metadata.cu =================================================================== --- clang/test/CodeGenCUDA/propagate-metadata.cu +++ clang/test/CodeGenCUDA/propagate-metadata.cu @@ -47,13 +47,14 @@ #endif } +// CHECK-NOT: convergent + // The kernel and lib function should have the same attributes. // CHECK: define void @kernel() [[attr:#[0-9]+]] // CHECK: define internal void @lib_fn() [[attr]] // Check the attribute list. // CHECK: attributes [[attr]] = { -// CHECK-SAME: convergent // CHECK-SAME: "no-trapping-math"="true" // FTZ-SAME: "nvptx-f32ftz"="true" Index: clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp =================================================================== --- clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -15,8 +15,8 @@ // CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } -// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RN]] = { noconvergent nounwind readnone{{.*}} } +// CHECK: attributes [[NUW_RO]] = { noconvergent nounwind readonly{{.*}} } // CHECK: attributes [[TF2]] = { {{.*}} } -// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RN_CALL]] = { noconvergent nounwind readnone } +// CHECK: attributes [[NUW_RO_CALL]] = { noconvergent nounwind readonly } Index: clang/test/CodeGenCXX/attr-x86-no_caller_saved_registers.cpp =================================================================== --- clang/test/CodeGenCXX/attr-x86-no_caller_saved_registers.cpp +++ clang/test/CodeGenCXX/attr-x86-no_caller_saved_registers.cpp @@ -28,4 +28,4 @@ // CHECK: attributes #[[ATTRS]] = { // CHECK-SAME: "no_caller_saved_registers" // CHECK-SAME: } -// CHECK: attributes #[[ATTRS1]] = { "no_caller_saved_registers" } +// CHECK: attributes #[[ATTRS1]] = { noconvergent "no_caller_saved_registers" } Index: clang/test/CodeGenCXX/attr.cpp =================================================================== --- clang/test/CodeGenCXX/attr.cpp +++ clang/test/CodeGenCXX/attr.cpp @@ -31,4 +31,4 @@ // CHECK at top of file extern "C" int test2() __attribute__((alias("_Z5test1v"))); -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/builtin-operator-new-delete.cpp =================================================================== --- clang/test/CodeGenCXX/builtin-operator-new-delete.cpp +++ clang/test/CodeGenCXX/builtin-operator-new-delete.cpp @@ -65,7 +65,7 @@ // CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}} -// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} +// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin noconvergent nounwind {{.*[}]}} // CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}} // CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}} Index: clang/test/CodeGenCXX/cxx11-exception-spec.cpp =================================================================== --- clang/test/CodeGenCXX/cxx11-exception-spec.cpp +++ clang/test/CodeGenCXX/cxx11-exception-spec.cpp @@ -121,8 +121,8 @@ } // CHECK: attributes [[NONE]] = { {{.*}} } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } -// CHECK: attributes [[NUW2]] = { nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } +// CHECK: attributes [[NUW2]] = { noconvergent nounwind{{.*}} } Index: clang/test/CodeGenCXX/cxx11-noreturn.cpp =================================================================== --- clang/test/CodeGenCXX/cxx11-noreturn.cpp +++ clang/test/CodeGenCXX/cxx11-noreturn.cpp @@ -7,4 +7,4 @@ while (g()) {} } -// CHECK: attributes [[NR]] = { noinline noreturn nounwind{{.*}} } +// CHECK: attributes [[NR]] = { noconvergent noinline noreturn nounwind{{.*}} } Index: clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp =================================================================== --- clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp +++ clang/test/CodeGenCXX/cxx1z-aligned-allocation.cpp @@ -54,11 +54,11 @@ void *a1(long n) { return new A[n]; } // CHECK-LABEL: define {{.*}} @_Z2a2P1A( -// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9 +// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #10 void a2(A *p) { delete p; } // CHECK-LABEL: define {{.*}} @_Z2a3P1A( -// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9 +// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #10 void a3(A *p) { delete[] p; } Index: clang/test/CodeGenCXX/debug-info-globalinit.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info-globalinit.cpp +++ clang/test/CodeGenCXX/debug-info-globalinit.cpp @@ -18,10 +18,10 @@ // CHECK-LABEL: define internal void @__cxx_global_var_init() // CHECK-NOT: __cxx_global_var_init -// CHECK: %[[C0:.+]] = call i32 @_Z4testv(), !dbg ![[LINE:.*]] +// CHECK: %[[C0:.+]] = call i32 @_Z4testv() #{{[0-9]+}}, !dbg ![[LINE:.*]] // CHECK-NOT: __cxx_global_var_init // CHECK: store i32 %[[C0]], i32* @_ZL1i, align 4, !dbg -// +// // CHECK-LABEL: define internal void @__cxx_global_var_init.1() // CHECK-NOT: dbg // CHECK: %[[C1:.+]] = call i32 @_Z4testv() @@ -30,9 +30,9 @@ // // CHECK-LABEL: define internal void @__cxx_global_var_init.2() // CHECK-NOT: __cxx_global_var_init -// CHECK: %[[C2:.+]] = call i32 @_Z4testv(), !dbg ![[LINE2:.*]] +// CHECK: %[[C2:.+]] = call i32 @_Z4testv() #{{[0-9]+}}, !dbg ![[LINE2:.*]] // CHECK-NOT: __cxx_global_var_init // CHECK: store i32 %[[C2]], i32* @_ZL1k, align 4, !dbg -// +// // CHECK: ![[LINE]] = !DILocation(line: 13, // CHECK: ![[LINE2]] = !DILocation(line: 15, Index: clang/test/CodeGenCXX/derived-to-base.cpp =================================================================== --- clang/test/CodeGenCXX/derived-to-base.cpp +++ clang/test/CodeGenCXX/derived-to-base.cpp @@ -1,17 +1,17 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s -struct A { - void f(); - +struct A { + void f(); + int a; }; -struct B : A { +struct B : A { double b; }; void f() { B b; - + b.f(); } @@ -46,4 +46,4 @@ } } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/dynamic-cast.cpp =================================================================== --- clang/test/CodeGenCXX/dynamic-cast.cpp +++ clang/test/CodeGenCXX/dynamic-cast.cpp @@ -20,5 +20,5 @@ // CHECK: declare i8* @__dynamic_cast(i8*, i8*, i8*, i64) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO]] = { noconvergent nounwind readonly } // CHECK: attributes [[NR]] = { noreturn } Index: clang/test/CodeGenCXX/exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/exceptions.cpp +++ clang/test/CodeGenCXX/exceptions.cpp @@ -594,4 +594,4 @@ // CHECK11: call void @_ZN6test121AdlEPvS1_(i8* [[PTR]], i8* [[PTR]]) } -// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind } +// CHECK98: attributes [[NI_NR_NUW]] = { noconvergent noinline noreturn nounwind } Index: clang/test/CodeGenCXX/global-dtor-no-atexit.cpp =================================================================== --- clang/test/CodeGenCXX/global-dtor-no-atexit.cpp +++ clang/test/CodeGenCXX/global-dtor-no-atexit.cpp @@ -43,4 +43,4 @@ static A a1, a2; } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/global-init.cpp =================================================================== --- clang/test/CodeGenCXX/global-init.cpp +++ clang/test/CodeGenCXX/global-init.cpp @@ -203,8 +203,8 @@ // rdar://problem/8090834: this should be nounwind // CHECK-NOEXC: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUW:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { -// CHECK-NOEXC: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK-NOEXC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } // PR21811: attach the appropriate attribute to the global init function // CHECK-FP: define internal void @_GLOBAL__sub_I_global_init.cpp() [[NUX:#[0-9]+]] section "__TEXT,__StaticInit,regular,pure_instructions" { -// CHECK-FP: attributes [[NUX]] = { noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} } +// CHECK-FP: attributes [[NUX]] = { noconvergent noinline nounwind {{.*}}"frame-pointer"="non-leaf"{{.*}} } Index: clang/test/CodeGenCXX/inline-hint.cpp =================================================================== --- clang/test/CodeGenCXX/inline-hint.cpp +++ clang/test/CodeGenCXX/inline-hint.cpp @@ -78,19 +78,19 @@ } // SUITABLE-NOT: attributes [[NOHINT_ATTR]] = { {{.*}}noinline{{.*}} } -// HINTED-DAG: attributes [[NOHINT_ATTR]] = { noinline{{.*}} } -// NOINLINE-DAG: attributes [[NOHINT_ATTR]] = { noinline{{.*}} } +// HINTED-DAG: attributes [[NOHINT_ATTR]] = { noconvergent noinline{{.*}} } +// NOINLINE-DAG: attributes [[NOHINT_ATTR]] = { noconvergent noinline{{.*}} } // SUITABLE-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } // HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } -// NOINLINE-DAG: attributes [[IMPLICIT_ATTR]] = { noinline{{.*}} } +// NOINLINE-DAG: attributes [[IMPLICIT_ATTR]] = { noconvergent noinline{{.*}} } // SUITABLE-NOT: attributes [[IMPLICIT_CONSTR_ATTR]] = { {{.*}}noinline{{.*}} } // HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } -// NOINLINE-DAG: attributes [[IMPLICIT_CONSTR_ATTR]] = { noinline{{.*}} } +// NOINLINE-DAG: attributes [[IMPLICIT_CONSTR_ATTR]] = { noconvergent noinline{{.*}} } // SUITABLE-NOT: attributes [[EXPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } // HINTED-NOT: attributes [[IMPLICIT_ATTR]] = { {{.*}}noinline{{.*}} } -// NOINLINE-DAG: attributes [[EXPLICIT_ATTR]] = { noinline{{.*}} } +// NOINLINE-DAG: attributes [[EXPLICIT_ATTR]] = { noconvergent noinline{{.*}} } -// CHECK-DAG: attributes [[OPTNONE_ATTR]] = { noinline{{.*}} } +// CHECK-DAG: attributes [[OPTNONE_ATTR]] = { noconvergent noinline{{.*}} } Index: clang/test/CodeGenCXX/inline-template-hint.cpp =================================================================== --- clang/test/CodeGenCXX/inline-template-hint.cpp +++ clang/test/CodeGenCXX/inline-template-hint.cpp @@ -18,7 +18,7 @@ inline void template_run(T); }; -// CHECK: @_ZN1A7int_runEi({{.*}}) [[ATTR:#[0-9]+]] +// CHECK: define {{.*}} @_ZN1A7int_runEi({{.*}}) [[ATTR:#[0-9]+]] void A::int_run(int) {} // CHECK: @_ZN1A12template_runIiEEvT_({{.*}}) [[ATTR]] template Index: clang/test/CodeGenCXX/main-norecurse.cpp =================================================================== --- clang/test/CodeGenCXX/main-norecurse.cpp +++ clang/test/CodeGenCXX/main-norecurse.cpp @@ -5,4 +5,4 @@ return 1; } -// CHECK: attributes #0 = { noinline norecurse{{.*}} } +// CHECK: attributes #0 = { noconvergent noinline norecurse{{.*}} } Index: clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp =================================================================== --- clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp +++ clang/test/CodeGenCXX/microsoft-abi-array-cookies.cpp @@ -68,4 +68,4 @@ void delete_s(S *s) { delete[] s; } } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/new-alias.cpp =================================================================== --- clang/test/CodeGenCXX/new-alias.cpp +++ clang/test/CodeGenCXX/new-alias.cpp @@ -9,5 +9,7 @@ void *operator new(size_t) __attribute__((alias("something"))); // PR16715: don't assert here. -// CHECK: call i8* @_Znwm(i64 4){{$}} +// CHECK: call i8* @_Znwm(i64 4) [[ATTR:#[0-9]+]]{{$}} int *pr16715 = new int; + +// CHECK: [[ATTR]] = { noconvergent } Index: clang/test/CodeGenCXX/new.cpp =================================================================== --- clang/test/CodeGenCXX/new.cpp +++ clang/test/CodeGenCXX/new.cpp @@ -1,376 +1,15 @@ -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -std=c++11 -o - %s | FileCheck %s -typedef __typeof__(sizeof(0)) size_t; +using size_t = decltype(sizeof(0)); -// Declare an 'operator new' template to tickle a bug in __builtin_operator_new. -template void *operator new(size_t, int (*)(T)); - -// Ensure that this declaration doesn't cause operator new to lose its -// 'noalias' attribute. -void *operator new[](size_t); - -void t1() { - delete new int; - delete [] new int [3]; -} - -// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]] -// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] -// CHECK: declare noalias i8* @_Znam(i64) [[ATTR_NOBUILTIN]] -// CHECK: declare void @_ZdaPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND]] - -namespace std { - struct nothrow_t {}; -} -std::nothrow_t nothrow; - -// Declare the reserved placement operators. -void *operator new(size_t, void*) throw(); -void operator delete(void*, void*) throw(); -void *operator new[](size_t, void*) throw(); -void operator delete[](void*, void*) throw(); - -// Declare the replaceable global allocation operators. -void *operator new(size_t, const std::nothrow_t &) throw(); -void *operator new[](size_t, const std::nothrow_t &) throw(); -void operator delete(void *, const std::nothrow_t &) throw(); -void operator delete[](void *, const std::nothrow_t &) throw(); - -// Declare some other placemenet operators. -void *operator new(size_t, void*, bool) throw(); -void *operator new[](size_t, void*, bool) throw(); - -void t2(int* a) { - int* b = new (a) int; -} - -struct S { - int a; -}; - -// POD types. -void t3() { - int *a = new int(10); - _Complex int* b = new _Complex int(10i); - - S s; - s.a = 10; - S *sp = new S(s); -} - -// Non-POD -struct T { - T(); - int a; -}; - -void t4() { - // CHECK: call void @_ZN1TC1Ev - T *t = new T; -} - -struct T2 { - int a; - T2(int, int); -}; - -void t5() { - // CHECK: call void @_ZN2T2C1Eii - T2 *t2 = new T2(10, 10); -} - -int *t6() { - // Null check. - return new (0) int(10); -} - -void t7() { - new int(); -} - -struct U { - ~U(); -}; - -void t8(int n) { - new int[10]; - new int[n]; - - // Non-POD - new T[10]; - new T[n]; - - // Cookie required - new U[10]; - new U[n]; -} - -void t9() { - bool b; - - new bool(true); - new (&b) bool(true); -} - -struct A { - void* operator new(__typeof(sizeof(int)), int, float, ...); - A(); -}; - -A* t10() { - // CHECK: @_ZN1AnwEmifz - return new(1, 2, 3.45, 100) A; -} - -// CHECK-LABEL: define void @_Z3t11i -struct B { int a; }; -struct Bmemptr { int Bmemptr::* memptr; int a; }; - -void t11(int n) { - // CHECK: call i8* @_Znwm - // CHECK: call void @llvm.memset.p0i8.i64( - B* b = new B(); - - // CHECK: call i8* @_Znam - // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} - B *b2 = new B[n](); - - // CHECK: call i8* @_Znam - // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 - // CHECK: br - Bmemptr *b_memptr = new Bmemptr[n](); - - // CHECK: ret void -} - -struct Empty { }; - -// We don't need to initialize an empty class. -// CHECK-LABEL: define void @_Z3t12v -void t12() { - // CHECK: call i8* @_Znam - // CHECK-NOT: br - (void)new Empty[10]; - - // CHECK: call i8* @_Znam - // CHECK-NOT: br - (void)new Empty[10](); - - // CHECK: ret void -} - -// Zero-initialization -// CHECK-LABEL: define void @_Z3t13i -void t13(int n) { - // CHECK: call i8* @_Znwm - // CHECK: store i32 0, i32* - (void)new int(); - - // CHECK: call i8* @_Znam - // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}} - (void)new int[n](); - - // CHECK-NEXT: ret void -} - -struct Alloc{ - int x; - void* operator new[](size_t size); - void operator delete[](void* p); - ~Alloc(); -}; - -void f() { - // CHECK: call i8* @_ZN5AllocnaEm(i64 808) - // CHECK: store i64 200 - // CHECK: call void @_ZN5AllocD1Ev( - // CHECK: call void @_ZN5AllocdaEPv(i8* - delete[] new Alloc[10][20]; - // CHECK: call i8* @_Znwm - // CHECK: call void @_ZdlPv(i8* - delete new bool; - // CHECK: ret void -} - -namespace test15 { - struct A { A(); ~A(); }; - - // CHECK-LABEL: define void @_ZN6test156test0aEPv( - // CHECK: [[P:%.*]] = load i8*, i8** - // CHECK-NOT: icmp eq i8* [[P]], null - // CHECK-NOT: br i1 - // CHECK: [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]* - // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T0]]) - void test0a(void *p) { - new (p) A(); - } - - // CHECK-LABEL: define void @_ZN6test156test0bEPv( - // CHECK: [[P0:%.*]] = load i8*, i8** - // CHECK: [[P:%.*]] = call i8* @_ZnwmPvb(i64 1, i8* [[P0]] - // CHECK-NEXT: icmp eq i8* [[P]], null - // CHECK-NEXT: br i1 - // CHECK: [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]* - // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T0]]) - void test0b(void *p) { - new (p, true) A(); - } - - // CHECK-LABEL: define void @_ZN6test156test1aEPv( - // CHECK: [[P:%.*]] = load i8*, i8** - // CHECK-NOT: icmp eq i8* [[P]], null - // CHECK-NOT: br i1 - // CHECK: [[BEGIN:%.*]] = bitcast i8* [[P]] to [[A:%.*]]* - // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 5 - // CHECK-NEXT: br label - // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] - // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[CUR]]) - // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]], [[A]]* [[CUR]], i64 1 - // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[END]] - // CHECK-NEXT: br i1 [[DONE]] - void test1a(void *p) { - new (p) A[5]; - } - - // CHECK-LABEL: define void @_ZN6test156test1bEPv( - // CHECK: [[P0:%.*]] = load i8*, i8** - // CHECK: [[P:%.*]] = call i8* @_ZnamPvb(i64 13, i8* [[P0]] - // CHECK-NEXT: icmp eq i8* [[P]], null - // CHECK-NEXT: br i1 - // CHECK: [[AFTER_COOKIE:%.*]] = getelementptr inbounds i8, i8* [[P]], i64 8 - // CHECK: [[BEGIN:%.*]] = bitcast i8* [[AFTER_COOKIE]] to [[A:%.*]]* - // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 5 - // CHECK-NEXT: br label - // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] - // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[CUR]]) - // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]], [[A]]* [[CUR]], i64 1 - // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[END]] - // CHECK-NEXT: br i1 [[DONE]] - void test1b(void *p) { - new (p, true) A[5]; - } - - // TODO: it's okay if all these size calculations get dropped. - // FIXME: maybe we should try to throw on overflow? - // CHECK-LABEL: define void @_ZN6test155test2EPvi( - // CHECK: [[N:%.*]] = load i32, i32* - // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64 - // CHECK-NEXT: [[P:%.*]] = load i8*, i8** - // CHECK: [[BEGIN:%.*]] = bitcast i8* [[P]] to [[A:%.*]]* - // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq i64 [[T0]], 0 - // CHECK-NEXT: br i1 [[ISEMPTY]], - // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 [[T0]] - // CHECK-NEXT: br label - // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], - // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[CUR]]) - void test2(void *p, int n) { - new (p) A[n]; - } -} - -namespace PR10197 { - // CHECK-LABEL: define weak_odr void @_ZN7PR101971fIiEEvv() - template - void f() { - // CHECK: [[CALL:%.*]] = call i8* @_Znwm - // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to - new T; - // CHECK-NEXT: ret void - } - - template void f(); -} - -namespace PR11523 { - class MyClass; - typedef int MyClass::* NewTy; - // CHECK-LABEL: define i64* @_ZN7PR115231fEv - // CHECK: store i64 -1 - NewTy* f() { return new NewTy[2](); } -} - -namespace PR11757 { - // Make sure we elide the copy construction. - struct X { X(); X(const X&); }; - X* a(X* x) { return new X(X()); } - // CHECK: define {{.*}} @_ZN7PR117571aEPNS_1XE - // CHECK: [[CALL:%.*]] = call i8* @_Znwm - // CHECK-NEXT: [[CASTED:%.*]] = bitcast i8* [[CALL]] to - // CHECK-NEXT: call void @_ZN7PR117571XC1Ev({{.*}}* [[CASTED]]) - // CHECK-NEXT: ret {{.*}} [[CASTED]] -} - -namespace PR13380 { - struct A { A() {} }; - struct B : public A { int x; }; - // CHECK-LABEL: define i8* @_ZN7PR133801fEv - // CHECK: call i8* @_Znam( - // CHECK: call void @llvm.memset.p0i8 - // CHECK-NEXT: call void @_ZN7PR133801BC1Ev - void* f() { return new B[2](); } -} - -struct MyPlacementType {} mpt; -void *operator new(size_t, MyPlacementType); - -namespace N3664 { - struct S { S() throw(int); }; - - // CHECK-LABEL: define void @_ZN5N36641fEv - void f() { - // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] - int *p = new int; // expected-note {{allocated with 'new' here}} - // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] - delete p; - - // CHECK: call i8* @_Znam(i64 12) [[ATTR_BUILTIN_NEW]] - int *q = new int[3]; - // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]] - delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}} - - // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_BUILTIN_NOTHROW_NEW:#[^ ]*]] - (void) new (nothrow) S[3]; - - // CHECK: call i8* @_Znwm15MyPlacementType(i64 4){{$}} - (void) new (mpt) int; - } - - // CHECK: declare noalias i8* @_ZnamRKSt9nothrow_t(i64, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND]] - - // CHECK-LABEL: define void @_ZN5N36641gEv - void g() { - // It's OK for there to be attributes here, so long as we don't have a - // 'builtin' attribute. - // CHECK: call i8* @_Znwm(i64 4){{$}} - int *p = (int*)operator new(4); - // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_NOUNWIND:#[^ ]*]] - operator delete(p); - - // CHECK: call i8* @_Znam(i64 12){{$}} - int *q = (int*)operator new[](12); - // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_NOUNWIND]] - operator delete [](p); - - // CHECK: call i8* @_ZnamRKSt9nothrow_t(i64 3, {{.*}}) [[ATTR_NOUNWIND]] - (void) operator new[](3, nothrow); - } -} - -namespace builtins { - // CHECK-LABEL: define void @_ZN8builtins1fEv - void f() { - // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW]] - // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]] - __builtin_operator_delete(__builtin_operator_new(4)); - } +extern "C" char *something(long long x) { } -// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin {{.*[}]}} -// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} +// CHECK: @_Znwm = alias i8* (i64), i8* (i64)* @something +void *operator new(size_t) __attribute__((alias("something"))); -// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}} -// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}} +// PR16715: don't assert here. +// CHECK: call i8* @_Znwm(i64 4) [[ATTR:#[0-9]+]]{{$}} +int *pr16715 = new int; -// The ([^b}|...) monstrosity is matching a character that's not the start of 'builtin'. -// Add more letters if this matches some other attribute. -// CHECK-DAG: attributes [[ATTR_NOUNWIND]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind {{([^b]|b[^u]|bu[^i]|bui[^l])*$}} +// CHECK: [[ATTR]] = { noconvergent } Index: clang/test/CodeGenCXX/no-exceptions.cpp =================================================================== --- clang/test/CodeGenCXX/no-exceptions.cpp +++ clang/test/CodeGenCXX/no-exceptions.cpp @@ -3,7 +3,7 @@ void g(); // CHECK: define void @_Z1fv() [[NUW:#[0-9]+]] -void f() throw (int) { +void f() throw (int) { // CHECK-NOT: invoke void @_Z1gv g(); @@ -11,4 +11,4 @@ // CHECK: ret void } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/noinline-template.cpp =================================================================== --- clang/test/CodeGenCXX/noinline-template.cpp +++ clang/test/CodeGenCXX/noinline-template.cpp @@ -15,4 +15,4 @@ strs.growStorageBy(); } -// CHECK: attributes [[NI]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NI]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/optnone-and-attributes.cpp =================================================================== --- clang/test/CodeGenCXX/optnone-and-attributes.cpp +++ clang/test/CodeGenCXX/optnone-and-attributes.cpp @@ -8,7 +8,7 @@ inline int func1(int a) { return a + a + a + a; } -// CHECK: @_Z5func1i({{.*}}) [[OPTNONE:#[0-9]+]] +// CHECK: dso_local i32 @_Z5func1i({{.*}}) [[OPTNONE:#[0-9]+]] // optnone declaration, inlinehint definition. __attribute__((optnone)) @@ -75,8 +75,8 @@ // CHECK: declare dllimport {{.*}} @_Z21imported_optnone_funci({{.*}}) [[DLLIMPORT:#[0-9]+]] -// CHECK: attributes [[OPTNONE]] = { noinline {{.*}} optnone -// CHECK: attributes [[NORETURN]] = { noinline noreturn {{.*}} optnone +// CHECK: attributes [[OPTNONE]] = { {{.*}} noinline {{.*}} optnone +// CHECK: attributes [[NORETURN]] = { {{.*}} noinline noreturn {{.*}} optnone // CHECK: attributes [[DLLIMPORT]] = // CHECK-NOT: optnone Index: clang/test/CodeGenCXX/optnone-class-members.cpp =================================================================== --- clang/test/CodeGenCXX/optnone-class-members.cpp +++ clang/test/CodeGenCXX/optnone-class-members.cpp @@ -13,7 +13,7 @@ static int static_optnone_method(int a) { return a + a; } - // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] + // CHECK: define {{.*}} @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] // Definition of an optnone normal method. __attribute__((optnone)) Index: clang/test/CodeGenCXX/optnone-def-decl.cpp =================================================================== --- clang/test/CodeGenCXX/optnone-def-decl.cpp +++ clang/test/CodeGenCXX/optnone-def-decl.cpp @@ -89,7 +89,7 @@ // CHECK: @_Z36user_of_forceinline_optnone_functionv() [[NORMAL]] // CHECK: @_Z28forceinline_optnone_functionii({{.*}}) [[OPTNONE]] -// CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} } +// CHECK: attributes [[OPTNONE]] = { noconvergent noinline nounwind optnone {{.*}} } // CHECK: attributes [[NORMAL]] = // CHECK-NOT: noinline // CHECK-NOT: optnone Index: clang/test/CodeGenCXX/optnone-templates.cpp =================================================================== --- clang/test/CodeGenCXX/optnone-templates.cpp +++ clang/test/CodeGenCXX/optnone-templates.cpp @@ -21,8 +21,8 @@ return template_normal(i) + template_optnone(i); } -// CHECK: @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]] -// CHECK: @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]] +// CHECK: define {{.*}} @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]] +// CHECK: define {{.*}} @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]] //-- Effect of optnone on a partial specialization. @@ -30,7 +30,7 @@ template class template_normal_base { public: - T method(T t, U u) + T method(T t, U u) { return t + static_cast(u); } @@ -48,7 +48,7 @@ // This function should cause an instantiation of the full template (whose // method is not marked optnone) and an instantiation of the partially // specialized template (whose method is marked optnone). -void container2() +void container2() { int y = 2; float z = 3.0; @@ -67,7 +67,7 @@ template class template_optnone_base { public: - __attribute__((optnone)) T method(T t, U u) + __attribute__((optnone)) T method(T t, U u) { return t + static_cast(u); } @@ -85,7 +85,7 @@ // This function should cause an instantiation of the full template (whose // method is marked optnone) and an instantiation of the partially // specialized template (whose method is not marked optnone). -void container3() +void container3() { int y = 2; float z = 3.0; Index: clang/test/CodeGenCXX/reference-cast.cpp =================================================================== --- clang/test/CodeGenCXX/reference-cast.cpp +++ clang/test/CodeGenCXX/reference-cast.cpp @@ -15,7 +15,7 @@ return 17; } -// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i16* @_Z20lvalue_integral_castv() +// CHECK-LABEL: define dereferenceable({{[0-9]+}}) i16* @_Z20lvalue_integral_castv() const short &lvalue_integral_cast() { if (i == 0) // CHECK: store i16 17, i16* @@ -193,4 +193,4 @@ // CHECK: store i64 } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/runtimecc.cpp =================================================================== --- clang/test/CodeGenCXX/runtimecc.cpp +++ clang/test/CodeGenCXX/runtimecc.cpp @@ -26,7 +26,7 @@ // CHECK-NEXT: ret void } -// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOUNWIND]] +// CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*) [[NOCONVERGENT_NOUNWIND:#[0-9]+]] namespace test1 { void test() { @@ -49,5 +49,6 @@ // CHECK: call void @__cxx_global_var_init() +// CHECK: attributes [[NOCONVERGENT_NOUNWIND]] = { noconvergent nounwind } // CHECK: attributes [[NOUNWIND]] = { nounwind } // CHECK: attributes [[NORETURN]] = { noreturn } Index: clang/test/CodeGenCXX/threadsafe-statics.cpp =================================================================== --- clang/test/CodeGenCXX/threadsafe-statics.cpp +++ clang/test/CodeGenCXX/threadsafe-statics.cpp @@ -10,7 +10,7 @@ // WITH-TSS: call i32 @__cxa_guard_acquire // WITH-TSS: call void @__cxa_guard_release // WITH-TSS: ret void -void g() { +void g() { static int a = f(); } @@ -22,6 +22,6 @@ // NO-TSS-NOT: call void @__cxa_guard_release // NO-TSS: ret void -// WITH-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} } +// WITH-TSS: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } -// NO-TSS: attributes [[NUW]] = { noinline nounwind{{.*}} } +// NO-TSS: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/thunks.cpp =================================================================== --- clang/test/CodeGenCXX/thunks.cpp +++ clang/test/CodeGenCXX/thunks.cpp @@ -30,7 +30,7 @@ struct C : A, B { virtual void c(); - + virtual void f(); }; @@ -83,7 +83,7 @@ struct B : A { virtual void b(); - + virtual V2 *f(); }; @@ -107,7 +107,7 @@ struct __attribute__((visibility("protected"))) C : A, B { virtual void c(); - + virtual void f(); }; @@ -142,8 +142,8 @@ void C::f() {} // Force C::f to be used. - void f() { - C c; + void f() { + C c; c.f(); } } @@ -542,5 +542,5 @@ // WIN64-LABEL: define linkonce_odr dso_local void @"?foo@C@Test10@@UEAAXXZ"( // WIN64-LABEL: define linkonce_odr dso_local void @"?foo@C@Test10@@W7EAAXXZ"( -// CHECK-NONOPT: attributes [[NUW]] = { noinline nounwind optnone uwtable{{.*}} } -// CHECK-OPT: attributes [[NUW]] = { nounwind uwtable{{.*}} } +// CHECK-NONOPT: attributes [[NUW]] = { noconvergent noinline nounwind optnone uwtable{{.*}} } +// CHECK-OPT: attributes [[NUW]] = { noconvergent nounwind uwtable{{.*}} } Index: clang/test/CodeGenCXX/virtual-base-cast.cpp =================================================================== --- clang/test/CodeGenCXX/virtual-base-cast.cpp +++ clang/test/CodeGenCXX/virtual-base-cast.cpp @@ -82,4 +82,4 @@ // MSVC: add nsw i32 4, %[[offset]] // MSVC: } -// CHECK: attributes [[NUW]] = { noinline nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenCXX/virtual-function-calls.cpp =================================================================== --- clang/test/CodeGenCXX/virtual-function-calls.cpp +++ clang/test/CodeGenCXX/virtual-function-calls.cpp @@ -13,7 +13,7 @@ a->f('c'); } -struct B : virtual A { +struct B : virtual A { virtual void f(); }; @@ -24,8 +24,8 @@ } namespace Test1 { - struct A { - virtual ~A(); + struct A { + virtual ~A(); }; struct B : A { @@ -47,10 +47,11 @@ // CHECK-INVARIANT-LABEL: define {{(dso_local )?}}void @_ZN15VirtualNoreturn1f void f(A *p) { p->f(); - // CHECK: call {{.*}}void %{{[^#]*$}} + // CHECK: call {{.*}}void %{{[^#]*}}[[ATTR:#[0-9]+]]{{$}} // CHECK-NOT: unreachable // CHECK-INVARIANT: load {{.*}} !invariant.load ![[EMPTY_NODE:[0-9]+]] } } +// CHECK: [[ATTR]] = { noconvergent } // CHECK-INVARIANT: ![[EMPTY_NODE]] = !{} Index: clang/test/CodeGenCXX/wasm-eh.cpp =================================================================== --- clang/test/CodeGenCXX/wasm-eh.cpp +++ clang/test/CodeGenCXX/wasm-eh.cpp @@ -35,7 +35,7 @@ // CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception(token %[[CATCHPAD]]) // CHECK-NEXT: store i8* %[[EXN]], i8** %exn.slot // CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]]) -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] @@ -53,7 +53,7 @@ // CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] // CHECK: [[CATCH_FALLTHROUGH_BB]] -// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #2 +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) // CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] // CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] @@ -144,7 +144,7 @@ // CHECK: [[CATCHSTART_BB]]: // CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*)] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD]]) ] // CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB:.*]] // CHECK: [[INVOKE_CONT_BB]]: @@ -172,7 +172,7 @@ // CHECK: [[CATCHSTART_BB]]: // CHECK: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* null] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD]]) ] // CHECK-NEXT: to label %[[INVOKE_CONT_BB0:.*]] unwind label %[[EHCLEANUP_BB:.*]] // CHECK: [[INVOKE_CONT_BB0]]: @@ -227,7 +227,7 @@ // CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[RETHROW_BB:.*]] // CHECK: [[CATCH_INT_BB]]: -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD]]) ] // CHECK-NEXT: to label %[[INVOKE_CONT_BB:.*]] unwind label %[[EHCLEANUP_BB2:.*]] // CHECK: [[INVOKE_CONT_BB]]: @@ -290,11 +290,11 @@ // CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD0]]) ] // CHECK: catchret from %[[CATCHPAD0]] to label -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD0]]) ] // CHECK: catchret from %[[CATCHPAD0]] to label @@ -313,11 +313,11 @@ // CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [i8* bitcast (i8** @_ZTIi to i8*), i8* null] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD1]]) ] // CHECK: catchret from %[[CATCHPAD1]] to label -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD1]]) ] // CHECK: invoke void @__cxa_end_catch() [ "funclet"(token %[[CATCHPAD1]]) ] @@ -360,13 +360,13 @@ // CHECK: %[[CATCHPAD0:.*]] = catchpad within %[[CATCHSWITCH0]] [i8* bitcast (i8** @_ZTIi to i8*)] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD0]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD0]]) ] // CHECK: %[[CATCHSWITCH1:.*]] = catchswitch within %[[CATCHPAD0]] // CHECK: %[[CATCHPAD1:.*]] = catchpad within %[[CATCHSWITCH1]] [i8* bitcast (i8** @_ZTIi to i8*)] -// CHECK: invoke void @_Z9may_throwv() [ "funclet"(token %[[CATCHPAD1]]) ] +// CHECK: invoke void @_Z9may_throwv() #{{[0-9]+}} [ "funclet"(token %[[CATCHPAD1]]) ] // CHECK: catchret from %[[CATCHPAD1]] to label Index: clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp =================================================================== --- clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp +++ clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp @@ -58,7 +58,7 @@ // CHECK-LPAD: invoke void @_Z9may_throwv() // CHECK-LPAD: to label %[[CONT:.+]] unwind label %[[CLEANUP:.+]] // CHECK-LPAD: [[CLEANUP]]: -// CHECK-LPAD: call void @_ZN7CleanupD1Ev(%struct.Cleanup* %x) #2 +// CHECK-LPAD: call void @_ZN7CleanupD1Ev(%struct.Cleanup* %x) // CHECK-LPAD: br label %[[CATCH:.+]] // CHECK-LPAD: [[CATCH]]: Index: clang/test/CodeGenObjC/arc-no-arc-exceptions.m =================================================================== --- clang/test/CodeGenObjC/arc-no-arc-exceptions.m +++ clang/test/CodeGenObjC/arc-no-arc-exceptions.m @@ -9,7 +9,7 @@ void not(void) __attribute__((nothrow)); // CHECK-LABEL: define void @test0( -// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @thrower() [[NOCONV:#[0-9]+]], !clang.arc.no_objc_arc_exceptions ! // CHECK: call void @not() [[NUW:#[0-9]+]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA-LABEL: define void @test0( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions @@ -20,7 +20,7 @@ } // CHECK-LABEL: define void @test1( -// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions ! +// CHECK: call void @thrower() [[NOCONV]], !clang.arc.no_objc_arc_exceptions ! // CHECK: call void @not() [[NUW]], !clang.arc.no_objc_arc_exceptions ! // NO-METADATA-LABEL: define void @test1( // NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions @@ -78,4 +78,5 @@ } } -// CHECK: attributes [[NUW]] = { nounwind } +// CHECK-DAG: attributes [[NOCONV]] = { noconvergent } +// CHECK-DAG: attributes [[NUW]] = { noconvergent nounwind } Index: clang/test/CodeGenObjC/arc.m =================================================================== --- clang/test/CodeGenObjC/arc.m +++ clang/test/CodeGenObjC/arc.m @@ -1557,6 +1557,6 @@ getAggDtor(); } -// ARC-ALIEN: attributes [[NLB]] = { nonlazybind } -// ARC-NATIVE: attributes [[NLB]] = { nonlazybind } +// ARC-ALIEN: attributes [[NLB]] = { noconvergent nonlazybind } +// ARC-NATIVE: attributes [[NLB]] = { noconvergent nonlazybind } // CHECK: attributes [[NUW]] = { nounwind } Index: clang/test/CodeGenObjC/attr-noreturn.m =================================================================== --- clang/test/CodeGenObjC/attr-noreturn.m +++ clang/test/CodeGenObjC/attr-noreturn.m @@ -13,7 +13,7 @@ + (void) abort __attribute__((noreturn)); - (void) fail __attribute__((noreturn)); @end - + @interface Derived : Middle @end @@ -22,7 +22,7 @@ [x fail]; } // CHECK-LABEL: @testInstanceMethod -// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}} +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NOCONV:#[0-9]+]]{{$}} // A direct call of a class method will normally never have a null receiver. void testClassMethod() { @@ -34,7 +34,7 @@ __attribute__((weak_import)) @interface WeakMiddle : Base @end - + @interface WeakDerived : WeakMiddle + (void) abort __attribute__((noreturn)); @end @@ -44,7 +44,7 @@ [WeakDerived abort]; } // CHECK-LABEL: @testWeakImport -// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}} +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NOCONV]]{{$}} @interface Derived (MyMethods) @end @@ -59,7 +59,7 @@ [self fail]; } // CHECK-LABEL: [Derived(MyMethods) testSelfInstanceMethod] -// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}} +// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NOCONV]]{{$}} // CHECK-ARC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NORETURN]] // The ARC rule doesn't apply in -init methods. @@ -69,14 +69,14 @@ return self; } // CHECK-LABEL: [Derived(MyMethods) initWhileTestingSelfInstanceMethod] -// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}} +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NOCONV]]{{$}} // Same thing applies to class methods. + (void) testSelfClassMethod { [self abort]; } // CHECK-LABEL: [Derived(MyMethods) testSelfClassMethod] -// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}} +// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NOCONV]]{{$}} // CHECK-ARC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NORETURN]] // Super invocations may never be used with a null pointer; this is a @@ -95,5 +95,6 @@ // CHECK: call void bitcast (i8* ([[SUPER_T]]*, i8*, ...)* @objc_msgSendSuper2 to void ([[SUPER_T]]*, i8*)*)([[SUPER_T]]* {{.*}}, i8* {{.*}}) [[NORETURN]] @end -// CHECK: attributes [[NORETURN]] = { noreturn } - \ No newline at end of file +// CHECK-DAG: attributes [[NORETURN]] = { noconvergent noreturn } +// CHECK-DAG: attributes [[NOCONV]] = { noconvergent } + Index: clang/test/CodeGenObjC/attr-objc-runtime-visible.m =================================================================== --- clang/test/CodeGenObjC/attr-objc-runtime-visible.m +++ clang/test/CodeGenObjC/attr-objc-runtime-visible.m @@ -14,6 +14,10 @@ // CHECK: [[CLASSNAME:@.*]] = private unnamed_addr constant [22 x i8] c"MyRuntimeVisibleClass // CHECK: define i8* @getClass() #0 { Class getClass(void) { - // CHECK: call i8* @objc_lookUpClass(i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[CLASSNAME]], i32 0, i32 0)) #2 + // CHECK: call i8* @objc_lookUpClass(i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[CLASSNAME]], i32 0, i32 0)) #3 return [A class]; } + +// CHECK: declare i8* @objc_lookUpClass(i8*) [[NOCONVERGENT:#[0-9]+]] + +// CHECK: attributes [[NOCONVERGENT]] = { noconvergent } Index: clang/test/CodeGenObjC/class-stubs.m =================================================================== --- clang/test/CodeGenObjC/class-stubs.m +++ clang/test/CodeGenObjC/class-stubs.m @@ -81,4 +81,4 @@ @end // -- calls to objc_loadClassRef() are readnone -// CHECK: attributes [[ATTRLIST]] = { nounwind nonlazybind readnone } +// CHECK: attributes [[ATTRLIST]] = { noconvergent nounwind nonlazybind readnone } Index: clang/test/CodeGenObjC/gnu-exceptions.m =================================================================== --- clang/test/CodeGenObjC/gnu-exceptions.m +++ clang/test/CodeGenObjC/gnu-exceptions.m @@ -32,4 +32,4 @@ log(1); } -// CHECK: attributes [[TF]] = { noinline optnone "{{.*}} } +// CHECK: attributes [[TF]] = { noconvergent noinline optnone "{{.*}} } Index: clang/test/CodeGenObjC/nonlazy-msgSend.m =================================================================== --- clang/test/CodeGenObjC/nonlazy-msgSend.m +++ clang/test/CodeGenObjC/nonlazy-msgSend.m @@ -5,4 +5,4 @@ [x foo]; } -// CHECK: attributes [[NLB]] = { nonlazybind } +// CHECK: attributes [[NLB]] = { noconvergent nonlazybind } Index: clang/test/CodeGenObjC/objc-literal-debugger-test.m =================================================================== --- clang/test/CodeGenObjC/objc-literal-debugger-test.m +++ clang/test/CodeGenObjC/objc-literal-debugger-test.m @@ -52,4 +52,4 @@ // CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]] -// CHECK: attributes [[NLB]] = { nonlazybind } +// CHECK: attributes [[NLB]] = { noconvergent nonlazybind } Index: clang/test/CodeGenObjC/objc-literal-tests.m =================================================================== --- clang/test/CodeGenObjC/objc-literal-tests.m +++ clang/test/CodeGenObjC/objc-literal-tests.m @@ -81,8 +81,8 @@ NSNumber *yesNumber1 = @YES; // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0 NSNumber *noNumber1 = @NO; -NSDictionary *dictionary = @{@"name" : NSUserName(), - @"date" : [NSDate date] }; +NSDictionary *dictionary = @{@"name" : NSUserName(), + @"date" : [NSDate date] }; return __objc_yes == __objc_no; } @@ -94,4 +94,4 @@ bar(^(void) { return YES; }); } -// CHECK: attributes [[NUW]] = { noinline {{(norecurse )?}}nounwind{{.*}} } +// CHECK: attributes [[NUW]] = { noconvergent noinline {{(norecurse )?}}nounwind{{.*}} } Index: clang/test/CodeGenObjCXX/arc-marker-funclet.mm =================================================================== --- clang/test/CodeGenObjCXX/arc-marker-funclet.mm +++ clang/test/CodeGenObjCXX/arc-marker-funclet.mm @@ -10,8 +10,10 @@ } } -// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ] +// CHECK: call i8* @"?f@@YAPAUobjc_object@@XZ"() [[NOCONV:#[0-9]+]] [ "funclet"(token %1) ] // CHECK-NEXT: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ] // The corresponding f() call was invoked from the entry basic block. // CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}} + +// CHECK: [[NOCONV]] = { noconvergent } Index: clang/test/CodeGenObjCXX/lambda-expressions.mm =================================================================== --- clang/test/CodeGenObjCXX/lambda-expressions.mm +++ clang/test/CodeGenObjCXX/lambda-expressions.mm @@ -164,5 +164,5 @@ #endif -// ARC: attributes [[NUW]] = { noinline nounwind{{.*}} } -// MRC: attributes [[NUW]] = { noinline nounwind{{.*}} } +// ARC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } +// MRC: attributes [[NUW]] = { noconvergent noinline nounwind{{.*}} } Index: clang/test/CodeGenOpenCL/amdgpu-attrs.cl =================================================================== --- clang/test/CodeGenOpenCL/amdgpu-attrs.cl +++ clang/test/CodeGenOpenCL/amdgpu-attrs.cl @@ -162,33 +162,33 @@ // CHECK-NOT: "amdgpu-num-sgpr"="0" // CHECK-NOT: "amdgpu-num-vgpr"="0" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" "amdgpu-implicitarg-num-bytes"="56" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" "amdgpu-implicitarg-num-bytes"="56" - -// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2" - -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" -// CHECK-DAG: attributes [[NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" - -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" - -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" - -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" -// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" - -// CHECK-DAG: attributes [[A_FUNCTION]] = { convergent noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" -// CHECK-DAG: attributes [[DEFAULT_KERNEL_ATTRS]] = { convergent noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_64_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="64,64" "amdgpu-implicitarg-num-bytes"="56" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_16_128]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="16,128" "amdgpu-implicitarg-num-bytes"="56" + +// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2" + +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" + +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" + +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" + +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" +// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="32,64" "amdgpu-implicitarg-num-bytes"="56" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" + +// CHECK-DAG: attributes [[A_FUNCTION]] = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" +// CHECK-DAG: attributes [[DEFAULT_KERNEL_ATTRS]] = { noinline nounwind optnone "amdgpu-flat-work-group-size"="1,256" "amdgpu-implicitarg-num-bytes"="56" Index: clang/test/CodeGenOpenCL/builtins-amdgcn.cl =================================================================== --- clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -441,7 +441,7 @@ } // CHECK-LABEL: @test_read_exec( -// CHECK: call i64 @llvm.read_register.i64(metadata ![[$EXEC:[0-9]+]]) #[[$READ_EXEC_ATTRS:[0-9]+]] +// CHECK: call i64 @llvm.read_register.i64(metadata ![[$EXEC:[0-9]+]]){{$}} void test_read_exec(global ulong* out) { *out = __builtin_amdgcn_read_exec(); } @@ -449,13 +449,13 @@ // CHECK: declare i64 @llvm.read_register.i64(metadata) #[[$NOUNWIND_READONLY:[0-9]+]] // CHECK-LABEL: @test_read_exec_lo( -// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_LO:[0-9]+]]) #[[$READ_EXEC_ATTRS]] +// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_LO:[0-9]+]]){{$}} void test_read_exec_lo(global uint* out) { *out = __builtin_amdgcn_read_exec_lo(); } // CHECK-LABEL: @test_read_exec_hi( -// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_HI:[0-9]+]]) #[[$READ_EXEC_ATTRS]] +// CHECK: call i32 @llvm.read_register.i32(metadata ![[$EXEC_HI:[0-9]+]]){{$}} void test_read_exec_hi(global uint* out) { *out = __builtin_amdgcn_read_exec_hi(); } @@ -699,7 +699,6 @@ // CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024} // CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly } -// CHECK-DAG: attributes #[[$READ_EXEC_ATTRS]] = { convergent } // CHECK-DAG: ![[$EXEC]] = !{!"exec"} // CHECK-DAG: ![[$EXEC_LO]] = !{!"exec_lo"} // CHECK-DAG: ![[$EXEC_HI]] = !{!"exec_hi"} Index: clang/test/CodeGenOpenCL/convergent.cl =================================================================== --- clang/test/CodeGenOpenCL/convergent.cl +++ clang/test/CodeGenOpenCL/convergent.cl @@ -11,7 +11,7 @@ *p = 0; } -void convfun(void) __attribute__((convergent)); +void convfun(void); void nodupfun(void) __attribute__((noduplicate)); // External functions should be assumed convergent. @@ -32,15 +32,14 @@ // CHECK: %[[tobool:.+]] = icmp eq i32 %a, 0 // CHECK: br i1 %[[tobool]], label %[[if_end3_critedge:.+]], label %[[if_then:.+]] -// CHECK: [[if_then]]: -// CHECK: tail call spir_func void @f() +// CHECK: [[if_end3_critedge]]: // CHECK: tail call spir_func void @non_convfun() -// CHECK: tail call spir_func void @g() - // CHECK: br label %[[if_end3:.+]] -// CHECK: [[if_end3_critedge]]: +// CHECK: [[if_then]]: +// CHECK: tail call spir_func void @f() // CHECK: tail call spir_func void @non_convfun() +// CHECK: tail call spir_func void @g() // CHECK: br label %[[if_end3]] // CHECK: [[if_end3]]: @@ -139,10 +138,10 @@ __asm__ volatile("s_barrier"); } -// CHECK: attributes #0 = { nofree noinline norecurse nounwind " -// CHECK: attributes #1 = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK: attributes #2 = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK: attributes #3 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } -// CHECK: attributes #4 = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK: attributes #5 = { {{[^}]*}}convergent{{[^}]*}} } -// CHECK: attributes #6 = { {{[^}]*}}convergent noduplicate{{[^}]*}} } +// CHECK: attributes #0 = { noconvergent nofree noinline norecurse nounwind " +// CHECK: attributes #1 = { nounwind " +// CHECK: attributes #2 = { " +// CHECK: attributes #3 = { noduplicate " +// CHECK: attributes #4 = { nounwind " +// CHECK: attributes #5 = { nounwind } +// CHECK: attributes #6 = { noduplicate nounwind } Index: clang/test/CodeGenOpenCL/func-call-dbg-loc.cl =================================================================== --- clang/test/CodeGenOpenCL/func-call-dbg-loc.cl +++ clang/test/CodeGenOpenCL/func-call-dbg-loc.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple amdgcn---amdgizcl -debug-info-kind=limited -O0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-- -debug-info-kind=limited -O0 -emit-llvm -o - %s | FileCheck %s typedef struct { @@ -11,8 +11,8 @@ void func3() { - // CHECK: call i32 @func1() #{{[0-9]+}}, !dbg ![[LOC:[0-9]+]] - // CHECK: call void @func2(i32 %{{[0-9]+}}) #{{[0-9]+}}, !dbg ![[LOC]] + // CHECK: call i32 @func1(), !dbg ![[LOC:[0-9]+]] + // CHECK: call void @func2(i32 %{{[0-9]+}}), !dbg ![[LOC]] func2(func1()); } Index: clang/test/CodeGenOpenCLCXX/template-address-spaces.cl =================================================================== --- clang/test/CodeGenOpenCLCXX/template-address-spaces.cl +++ clang/test/CodeGenOpenCLCXX/template-address-spaces.cl @@ -14,11 +14,11 @@ // CHECK: %struct.S.1 = type { i32 addrspace(1)* } // CHECK: [[A1:%[.a-z0-9]+]] = addrspacecast %struct.S* %{{[a-z0-9]+}} to %struct.S addrspace(4)* -// CHECK: %call = call spir_func i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* [[A1]]) #1 +// CHECK: %call = call spir_func i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* [[A1]]) // CHECK: [[A2:%[.a-z0-9]+]] = addrspacecast %struct.S.0* %{{[a-z0-9]+}} to %struct.S.0 addrspace(4)* -// CHECK: %call1 = call spir_func i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* [[A2]]) #1 +// CHECK: %call1 = call spir_func i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* [[A2]]) // CHECK: [[A3:%[.a-z0-9]+]] = addrspacecast %struct.S.1* %{{[a-z0-9]+}} to %struct.S.1 addrspace(4)* -// CHECK: %call2 = call spir_func i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* [[A3]]) #1 +// CHECK: %call2 = call spir_func i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* [[A3]]) void bar(){ S sint; Index: clang/test/Driver/darwin-iphone-defaults.m =================================================================== --- clang/test/Driver/darwin-iphone-defaults.m +++ clang/test/Driver/darwin-iphone-defaults.m @@ -26,4 +26,4 @@ [I1 alloc]; } -// CHECK: attributes [[F0]] = { noinline optnone ssp{{.*}} } +// CHECK: attributes [[F0]] = { noconvergent noinline optnone ssp{{.*}} } Index: clang/test/OpenMP/nvptx_parallel_codegen.cpp =================================================================== --- clang/test/OpenMP/nvptx_parallel_codegen.cpp +++ clang/test/OpenMP/nvptx_parallel_codegen.cpp @@ -88,7 +88,7 @@ // CHECK: br label {{%?}}[[AWAIT_WORK:.+]] // // CHECK: [[AWAIT_WORK]] -// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) #[[#CONVERGENT:]] +// CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0){{$}} // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]] // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 @@ -318,10 +318,10 @@ // CHECK: define internal void [[PARALLEL_FN4]]( // CHECK: [[A:%.+]] = alloca i[[SZ:32|64]], // CHECK: store i[[SZ]] 45, i[[SZ]]* %a, -// CHECK: call void @__kmpc_barrier(%struct.ident_t* @{{.+}}, i32 %{{.+}}) #[[#CONVERGENT:]] +// CHECK: call void @__kmpc_barrier(%struct.ident_t* @{{.+}}, i32 %{{.+}}){{$}} // CHECK: ret void -// CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) #[[#CONVERGENT]] +// CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32){{$}} // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}_worker() // CHECK-LABEL: define {{.*}}void {{@__omp_offloading_.+template.+l55}}( @@ -369,9 +369,8 @@ // CHECK: br label -// CHECK: declare i32 @__kmpc_warp_active_thread_mask() #[[#CONVERGENT:]] -// CHECK: declare void @__kmpc_syncwarp(i32) #[[#CONVERGENT:]] - -// CHECK: attributes #[[#CONVERGENT]] = {{.*}} convergent {{.*}} +// no noconvergent attribute +// CHECK: declare i32 @__kmpc_warp_active_thread_mask(){{$}} +// CHECK: declare void @__kmpc_syncwarp(i32){{$}} #endif Index: clang/test/OpenMP/openmp_win_codegen.cpp =================================================================== --- clang/test/OpenMP/openmp_win_codegen.cpp +++ clang/test/OpenMP/openmp_win_codegen.cpp @@ -61,9 +61,9 @@ // CHECK-NEXT: call void @__kmpc_end_critical(%struct.ident_t* {{.*}}@0, i32 [[GID]], // CHECK-NEXT: cleanupret from {{.*}} unwind label %[[CATCHTERM:[^ ]+]] // CHECK: cleanuppad within none [] -// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #{{[0-9]+}} [ "funclet"(token %{{.*}}) ] // CHECK-NEXT: unreachable // CHECK: [[CATCHTERM]] // CHECK-NEXT: cleanuppad within [[CATCHPAD]] [] -// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #5 [ "funclet"(token %{{.*}}) ] +// CHECK-NEXT: call void @"?terminate@@YAXXZ"() #{{[0-9]+}} [ "funclet"(token %{{.*}}) ] // CHECK-NEXT: unreachable Index: clang/test/PCH/objc_container.m =================================================================== --- clang/test/PCH/objc_container.m +++ clang/test/PCH/objc_container.m @@ -3,7 +3,7 @@ // Test with pch. // RUN: %clang_cc1 -x objective-c -emit-pch -o %t %S/objc_container.h -// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s // RUN: %clang_cc1 -include-pch %t -ast-print %s | FileCheck -check-prefix=CHECK-PRINT %s // RUN: %clang_cc1 -include-pch %t -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-IR %s @@ -21,5 +21,5 @@ // CHECK-IR: {{call.*objc_msgSend}} // CHECK-IR: ret void -// CHECK-IR: attributes #0 = { noinline nounwind {{.*}} } -// CHECK-IR: attributes #1 = { nonlazybind } +// CHECK-IR: attributes #0 = { noconvergent noinline nounwind {{.*}} } +// CHECK-IR: attributes #1 = { noconvergent nonlazybind } Index: clang/test/Sema/libbuiltins-ctype-powerpc64.c =================================================================== --- clang/test/Sema/libbuiltins-ctype-powerpc64.c +++ clang/test/Sema/libbuiltins-ctype-powerpc64.c @@ -61,5 +61,5 @@ // CHECK: declare signext i32 @tolower(i32 signext) [[NUW_RO:#[0-9]+]] // CHECK: declare signext i32 @toupper(i32 signext) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO]] = { noconvergent nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RO_CALL]] = { noconvergent nounwind readonly } Index: clang/test/Sema/libbuiltins-ctype-x86_64.c =================================================================== --- clang/test/Sema/libbuiltins-ctype-x86_64.c +++ clang/test/Sema/libbuiltins-ctype-x86_64.c @@ -61,5 +61,5 @@ // CHECK: declare i32 @tolower(i32) [[NUW_RO:#[0-9]+]] // CHECK: declare i32 @toupper(i32) [[NUW_RO:#[0-9]+]] -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO]] = { noconvergent nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RO_CALL]] = { noconvergent nounwind readonly } Index: clang/test/SemaCXX/pragma-optimize.cpp =================================================================== --- clang/test/SemaCXX/pragma-optimize.cpp +++ clang/test/SemaCXX/pragma-optimize.cpp @@ -89,7 +89,7 @@ return thrice(par); } // CHECK-DAG: @_Z10container2f{{.*}} [[ATTRCONTAINER2:#[0-9]+]] -// CHECK-DAG: @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]] +// CHECK-DAG: define linkonce_odr float @_Z6thriceIfET_S0_{{.*}} [[ATTRTHRICEFLOAT:#[0-9]+]] // A template specialization is a new definition and it will not be Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -801,6 +801,15 @@ [parameter Attrs] [name] + .. _convergence: + +Convergence +--------- + +In some parallel execution models, there exist operations that cannot +be made control-dependent on any additional values. We call such +operations convergent. By default, functions are assumed to have +convergent semantics. .. _langref_aliases: @@ -1389,27 +1398,30 @@ computing edge weights, basic blocks post-dominated by a cold function call are also considered to be cold; and, thus, given low weight. -``convergent`` - In some parallel execution models, there exist operations that cannot be - made control-dependent on any additional values. We call such operations - ``convergent``, and mark them with this attribute. - - The ``convergent`` attribute may appear on functions or call/invoke - instructions. When it appears on a function, it indicates that calls to - this function should not be made control-dependent on additional values. - For example, the intrinsic ``llvm.nvvm.barrier0`` is ``convergent``, so - calls to this intrinsic cannot be made control-dependent on additional +``noconvergent`` + This indicates that the function does not call any `convergent + ` operations. The absence of this attributes implies + such operations may be called. + + The ``noconvergent`` attribute may appear on functions or + call/invoke instructions. When it appears on a function, it + indicates that calls to this function may be made + control-dependent on additional values. For example, the + intrinsic ``llvm.nvvm.barrier0`` is not ``noconvergent``, so calls + to this intrinsic cannot be made control-dependent on additional values. - When it appears on a call/invoke, the ``convergent`` attribute indicates - that we should treat the call as though we're calling a convergent + When it appears on a call/invoke, the ``noconvergent`` attribute indicates + that we should treat the call as though we're calling a ``noconvergent`` function. This is particularly useful on indirect calls; without this we - may treat such calls as though the target is non-convergent. + may treat such calls as though the target is `convergent `. + + The optimizer may add the ``noconvergent`` attribute on functions + when it can prove that the function does not execute any + convergent operations. Similarly, the optimizer may add + ``noconvergent`` on calls/invokes when it can prove that the + call/invoke cannot call a convergent function. - The optimizer may remove the ``convergent`` attribute on functions when it - can prove that the function does not execute any convergent operations. - Similarly, the optimizer may remove ``convergent`` on calls/invokes when it - can prove that the call/invoke cannot call a convergent function. ``inaccessiblememonly`` This attribute indicates that the function may only access memory that is not accessible by the module being compiled. This is a weaker form @@ -1503,15 +1515,17 @@ If an invocation of an annotated function does not return control back to a point in the call stack, the behavior is undefined. ``nosync`` - This function attribute indicates that the function does not communicate - (synchronize) with another thread through memory or other well-defined means. - Synchronization is considered possible in the presence of `atomic` accesses - that enforce an order, thus not "unordered" and "monotonic", `volatile` accesses, - as well as `convergent` function calls. Note that through `convergent` function calls - non-memory communication, e.g., cross-lane operations, are possible and are also - considered synchronization. However `convergent` does not contradict `nosync`. - If an annotated function does ever synchronize with another thread, - the behavior is undefined. + This function attribute indicates that the function does not + communicate (synchronize) with another thread through memory or + other well-defined means. Synchronization is considered possible + in the presence of `atomic` accesses that enforce an order, thus + not "unordered" and "monotonic", `volatile` accesses, as well as + `convergent` function calls. Note that through `convergent` + function calls non-memory communication, e.g., cross-lane + operations, are possible and are also considered + synchronization. However the abcense of ``noconvergent`` does not + contradict `nosync`. If an annotated function does ever + synchronize with another thread, the behavior is undefined. ``nounwind`` This function attribute indicates that the function never raises an exception. If the function does raise an exception, its runtime @@ -15109,9 +15123,9 @@ data arguments and the return value are the same as the corresponding FP operation. -The rounding mode argument is a metadata string specifying what -assumptions, if any, the optimizer can make when transforming constant -values. Some constrained FP intrinsics omit this argument. If required +The rounding mode argument is a metadata string specifying what +assumptions, if any, the optimizer can make when transforming constant +values. Some constrained FP intrinsics omit this argument. If required by the intrinsic, this argument must be one of the following strings: :: Index: llvm/docs/ReleaseNotes.rst =================================================================== --- llvm/docs/ReleaseNotes.rst +++ llvm/docs/ReleaseNotes.rst @@ -86,6 +86,11 @@ Changes to the LLVM IR ---------------------- +* Functions are now assumed to potentially have convergent semantics + by default. The convergent attribute has been removed, as it is now + the default. Languages or targets without convergent semantics + should add the new noconvergent attribute to all functions. + * Unnamed function arguments now get printed with their automatically generated name (e.g. "i32 %0") in definitions. This may require front-ends to update their tests; if so there is a script utils/add_argument_names.py Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -632,6 +632,7 @@ ATTR_KIND_NOFREE = 62, ATTR_KIND_NOSYNC = 63, ATTR_KIND_SANITIZE_MEMTAG = 64, + ATTR_KIND_NOCONVERGENT = 65, }; enum ComdatSelectionKindCodes { Index: llvm/include/llvm/IR/Attributes.td =================================================================== --- llvm/include/llvm/IR/Attributes.td +++ llvm/include/llvm/IR/Attributes.td @@ -36,8 +36,9 @@ /// Marks function as being in a cold path. def Cold : EnumAttr<"cold">; -/// Can only be moved to control-equivalent blocks. -def Convergent : EnumAttr<"convergent">; +/// Function is not a convergent intrinsic call and does not call any +/// functions that may be convergent. +def NoConvergent : EnumAttr<"noconvergent">; /// Pointer is known to be dereferenceable. def Dereferenceable : EnumAttr<"dereferenceable">; Index: llvm/include/llvm/IR/CallSite.h =================================================================== --- llvm/include/llvm/IR/CallSite.h +++ llvm/include/llvm/IR/CallSite.h @@ -534,11 +534,13 @@ bool isConvergent() const { CALLSITE_DELEGATE_GETTER(isConvergent()); } - void setConvergent() { - CALLSITE_DELEGATE_SETTER(setConvergent()); + + bool isNoConvergent() const { + CALLSITE_DELEGATE_GETTER(isNoConvergent()); } - void setNotConvergent() { - CALLSITE_DELEGATE_SETTER(setNotConvergent()); + + void setNoConvergent() { + CALLSITE_DELEGATE_SETTER(setNoConvergent()); } unsigned getNumOperandBundles() const { Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -550,15 +550,16 @@ addFnAttr(Attribute::NoDuplicate); } - /// Determine if the call is convergent. - bool isConvergent() const { - return hasFnAttribute(Attribute::Convergent); + /// Determine if the call is not convergent. + bool isNoConvergent() const { + return hasFnAttribute(Attribute::NoConvergent); } - void setConvergent() { - addFnAttr(Attribute::Convergent); + + void setNoConvergent() { + addFnAttr(Attribute::NoConvergent); } - void setNotConvergent() { - removeFnAttr(Attribute::Convergent); + void setNotNoConvergent() { + removeFnAttr(Attribute::NoConvergent); } /// Determine if the call has sideeffects. Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -1698,12 +1698,17 @@ } /// Determine if the invoke is convergent - bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } - void setConvergent() { - addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); + bool isConvergent() const { return !hasFnAttr(Attribute::NoConvergent); } + + /// Determine if the invoke is noconvergent + bool isNoConvergent() const { return hasFnAttr(Attribute::NoConvergent); } + + void setNoConvergent() { + addAttribute(AttributeList::FunctionIndex, Attribute::NoConvergent); } - void setNotConvergent() { - removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent); + + void setConvergent() { + removeAttribute(AttributeList::FunctionIndex, Attribute::NoConvergent); } /// Determine if the call returns a structure through first Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -427,9 +427,9 @@ def int_frameaddress : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_sponentry : Intrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrReadMem], "llvm.read_register">; + [IntrReadMem, IntrConvergent], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], - [], "llvm.write_register">; + [IntrConvergent], "llvm.write_register">; // Gets the address of the local variable area. This is typically a copy of the // stack, frame, or base pointer depending on the type of prologue. Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1475,6 +1475,24 @@ static const char ID; }; +struct AANoConvergent + : public IRAttribute> { + AANoConvergent(const IRPosition &IRP) : IRAttribute(IRP) {} + + /// Returns true if noconvergent is assumed. + bool isAssumedNoConvergent() const { return getAssumed(); } + + /// Returns true if noconvergent is known. + bool isKnownNoConvergent() const { return getKnown(); } + + /// Create an abstract attribute view for the position \p IRP. + static AANoConvergent &createForPosition(const IRPosition &IRP, Attributor &A); + + /// Unique ID (due to the unique address) + static const char ID; +}; + struct AANoSync : public IRAttribute> { Index: llvm/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/lib/AsmParser/LLLexer.cpp +++ llvm/lib/AsmParser/LLLexer.cpp @@ -637,6 +637,7 @@ KEYWORD(inalloca); KEYWORD(cold); KEYWORD(convergent); + KEYWORD(noconvergent); KEYWORD(dereferenceable); KEYWORD(dereferenceable_or_null); KEYWORD(inaccessiblememonly); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1270,7 +1270,10 @@ case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; - case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; + case lltok::kw_convergent: + HaveError |= Error(Lex.getLoc(), "convergent attribute removed"); + break; + case lltok::kw_noconvergent: B.addAttribute(Attribute::NoConvergent); break; case lltok::kw_inaccessiblememonly: B.addAttribute(Attribute::InaccessibleMemOnly); break; case lltok::kw_inaccessiblemem_or_argmemonly: @@ -1682,6 +1685,7 @@ case lltok::kw_shadowcallstack: case lltok::kw_strictfp: case lltok::kw_uwtable: + case lltok::kw_noconvergent: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); break; } @@ -1781,6 +1785,7 @@ case lltok::kw_shadowcallstack: case lltok::kw_strictfp: case lltok::kw_uwtable: + case lltok::kw_noconvergent: HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute"); break; Index: llvm/lib/AsmParser/LLToken.h =================================================================== --- llvm/lib/AsmParser/LLToken.h +++ llvm/lib/AsmParser/LLToken.h @@ -183,6 +183,7 @@ kw_inalloca, kw_cold, kw_convergent, + kw_noconvergent, kw_dereferenceable, kw_dereferenceable_or_null, kw_inaccessiblememonly, Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1258,7 +1258,7 @@ case Attribute::InAlloca: return 1ULL << 43; case Attribute::NonNull: return 1ULL << 44; case Attribute::JumpTable: return 1ULL << 45; - case Attribute::Convergent: return 1ULL << 46; + // Removed Convergent , 1ULL << 46 case Attribute::SafeStack: return 1ULL << 47; case Attribute::NoRecurse: return 1ULL << 48; case Attribute::InaccessibleMemOnly: return 1ULL << 49; @@ -1299,6 +1299,10 @@ case Attribute::SanitizeMemTag: llvm_unreachable("sanitize_memtag attribute not supported in raw format"); break; + case Attribute::NoConvergent: + // FIXME: Should steal noduplicate or convergent's bit + llvm_unreachable("noconvergent attribute not supported in raw format"); + break; } llvm_unreachable("Unsupported attribute type"); } @@ -1313,7 +1317,8 @@ I == Attribute::DereferenceableOrNull || I == Attribute::ArgMemOnly || I == Attribute::AllocSize || - I == Attribute::NoSync) + I == Attribute::NoSync || + I == Attribute::NoConvergent) continue; if (uint64_t A = (Val & getRawAttributeMask(I))) { if (I == Attribute::Alignment) @@ -1427,7 +1432,11 @@ case bitc::ATTR_KIND_COLD: return Attribute::Cold; case bitc::ATTR_KIND_CONVERGENT: - return Attribute::Convergent; + // Upgrade convergent by ignoring it. The new default behavior matches + // the old attributed semantics. + return Attribute::EndAttrKinds; + case bitc::ATTR_KIND_NOCONVERGENT: + return Attribute::NoConvergent; case bitc::ATTR_KIND_INACCESSIBLEMEM_ONLY: return Attribute::InaccessibleMemOnly; case bitc::ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY: @@ -1609,6 +1618,9 @@ if (Error Err = parseAttrKind(Record[++i], &Kind)) return Err; + if (Kind == Attribute::EndAttrKinds) // Removed attribute + continue; + // Upgrade old-style byval attribute to one with a type, even if it's // nullptr. We will have to insert the real type when we associate // this AttributeList with a function. Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -609,8 +609,8 @@ return bitc::ATTR_KIND_BUILTIN; case Attribute::ByVal: return bitc::ATTR_KIND_BY_VAL; - case Attribute::Convergent: - return bitc::ATTR_KIND_CONVERGENT; + case Attribute::NoConvergent: + return bitc::ATTR_KIND_NOCONVERGENT; case Attribute::InAlloca: return bitc::ATTR_KIND_IN_ALLOCA; case Attribute::Cold: Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -288,8 +288,8 @@ return "argmemonly"; if (hasAttribute(Attribute::Builtin)) return "builtin"; - if (hasAttribute(Attribute::Convergent)) - return "convergent"; + if (hasAttribute(Attribute::NoConvergent)) + return "noconvergent"; if (hasAttribute(Attribute::SwiftError)) return "swifterror"; if (hasAttribute(Attribute::SwiftSelf)) Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1535,7 +1535,7 @@ case Attribute::OptForFuzzing: case Attribute::OptimizeNone: case Attribute::JumpTable: - case Attribute::Convergent: + case Attribute::NoConvergent: case Attribute::ArgMemOnly: case Attribute::NoRecurse: case Attribute::InaccessibleMemOnly: Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -850,6 +850,72 @@ void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); } }; +/// -----------------------NoConvergent Function Attribute-------------------------- + +struct AANoConvergentImpl : AANoConvergent { + AANoConvergentImpl(const IRPosition &IRP) : AANoConvergent(IRP) {} + + const std::string getAsStr() const override { + return getAssumed() ? "noconvergent" : "convergent"; + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + auto CheckForNoConvergent = [&](Instruction &I) { + if (ImmutableCallSite ICS = ImmutableCallSite(&I)) { + const auto &NoConvergentAA = + A.getAAFor(*this, IRPosition::callsite_function(ICS)); + return NoConvergentAA.isAssumedNoConvergent(); + } + + // Only call-like instructions may be convergent. + return true; + }; + + if (!A.checkForAllInstructions(CheckForNoConvergent, *this, CallLikeOpcodes)) + return indicatePessimisticFixpoint(); + + return ChangeStatus::UNCHANGED; + } +}; + +struct AANoConvergentFunction final : public AANoConvergentImpl { + AANoConvergentFunction(const IRPosition &IRP) : AANoConvergentImpl(IRP) {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noconvergent) } +}; + +/// NoConvergent attribute deduction for a call sites. +struct AANoConvergentCallSite final : AANoConvergentImpl { + AANoConvergentCallSite(const IRPosition &IRP) : AANoConvergentImpl(IRP) {} + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + AANoConvergentImpl::initialize(A); + Function *F = getAssociatedFunction(); + if (!F) + indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + // TODO: Once we have call site specific value information we can provide + // call site specific liveness information and then it makes + // sense to specialize attributes for call sites arguments instead of + // redirecting requests to the callee argument. + Function *F = getAssociatedFunction(); + const IRPosition &FnPos = IRPosition::function(*F); + auto &FnAA = A.getAAFor(*this, FnPos); + return clampStateAndIndicateChange( + getState(), + static_cast(FnAA.getState())); + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noconvergent); } +}; + /// --------------------- Function Return Values ------------------------------- /// "Attribute" that collects all potential returned values and the return @@ -1423,7 +1489,7 @@ return true; // non-convergent and readnone imply nosync. - return !ImmutableCallSite(&I).isConvergent(); + return ImmutableCallSite(&I).isNoConvergent(); }; if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this) || @@ -4739,6 +4805,9 @@ // Every function can be nounwind. getOrCreateAAFor(FPos); + // Every function can be noconvergent + getOrCreateAAFor(FPos); + // Every function might be marked "nosync" getOrCreateAAFor(FPos); @@ -5007,6 +5076,7 @@ const char AAReturnedValues::ID = 0; const char AANoUnwind::ID = 0; +const char AANoConvergent::ID = 0; const char AANoSync::ID = 0; const char AANoFree::ID = 0; const char AANonNull::ID = 0; @@ -5115,6 +5185,7 @@ } CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind) +CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoConvergent) CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync) CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree) CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse) Index: llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -29,7 +29,7 @@ .Case("alwaysinline", Attribute::AlwaysInline) .Case("builtin", Attribute::Builtin) .Case("cold", Attribute::Cold) - .Case("convergent", Attribute::Convergent) + .Case("noconvergent", Attribute::NoConvergent) .Case("inlinehint", Attribute::InlineHint) .Case("jumptable", Attribute::JumpTable) .Case("minsize", Attribute::MinSize) Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -77,6 +77,7 @@ STATISTIC(NumNoRecurse, "Number of functions marked as norecurse"); STATISTIC(NumNoUnwind, "Number of functions marked as nounwind"); STATISTIC(NumNoFree, "Number of functions marked as nofree"); +STATISTIC(NumNoConvergent, "Number of functions marked as noconvergent"); static cl::opt EnableNonnullArgPropagation( "enable-nonnull-arg-prop", cl::init(true), cl::Hidden, @@ -1219,13 +1220,13 @@ } // end anonymous namespace -/// Helper for non-Convergent inference predicate InstrBreaksAttribute. -static bool InstrBreaksNonConvergent(Instruction &I, +/// Helper for NoConvergent inference predicate InstrBreaksAttribute. +static bool InstrBreaksNoConvergent(Instruction &I, const SCCNodeSet &SCCNodes) { const CallSite CS(&I); // Breaks non-convergent assumption if CS is a convergent call to a function // not in the SCC. - return CS && CS.isConvergent() && SCCNodes.count(CS.getCalledFunction()) == 0; + return CS && !CS.isNoConvergent() && SCCNodes.count(CS.getCalledFunction()) == 0; } /// Helper for NoUnwind inference predicate InstrBreaksAttribute. @@ -1274,26 +1275,6 @@ AttributeInferer AI; - // Request to remove the convergent attribute from all functions in the SCC - // if every callsite within the SCC is not convergent (except for calls - // to functions within the SCC). - // Note: Removal of the attr from the callsites will happen in - // InstCombineCalls separately. - AI.registerAttrInference(AttributeInferer::InferenceDescriptor{ - Attribute::Convergent, - // Skip non-convergent functions. - [](const Function &F) { return !F.isConvergent(); }, - // Instructions that break non-convergent assumption. - [SCCNodes](Instruction &I) { - return InstrBreaksNonConvergent(I, SCCNodes); - }, - [](Function &F) { - LLVM_DEBUG(dbgs() << "Removing convergent attr from fn " << F.getName() - << "\n"); - F.setNotConvergent(); - }, - /* RequiresExactDefinition= */ false}); - if (!DisableNoUnwindInference) // Request to infer nounwind attribute for all the functions in the SCC if // every callsite within the SCC is not throwing (except for calls to @@ -1339,6 +1320,24 @@ }, /* RequiresExactDefinition= */ true}); + + AI.registerAttrInference(AttributeInferer::InferenceDescriptor{ + Attribute::NoConvergent, + // Skip noconvergent functions. + [](const Function &F) { return F.isNoConvergent(); }, + // Instructions that break non-throwing assumption. + [SCCNodes](Instruction &I) { + return InstrBreaksNoConvergent(I, SCCNodes); + }, + [](Function &F) { + LLVM_DEBUG(dbgs() + << "Adding noconvergent attr to fn " << F.getName() << '\n'); + F.setNoConvergent(); + ++NumNoConvergent; + }, + /* RequiresExactDefinition= */ true}); + + // Perform all the requested attribute inference actions. return AI.run(SCCNodes); } Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3692,8 +3692,6 @@ MDNode *MD = MDNode::get(II->getContext(), MDArgs); Value *Args[] = {MetadataAsValue::get(II->getContext(), MD)}; CallInst *NewCall = Builder.CreateCall(NewF, Args); - NewCall->addAttribute(AttributeList::FunctionIndex, - Attribute::Convergent); NewCall->takeName(II); return replaceInstUsesWith(*II, NewCall); } @@ -4301,15 +4299,6 @@ return nullptr; if (Function *CalleeF = dyn_cast(Callee)) { - // Remove the convergent attr on calls when the callee is not convergent. - if (Call.isConvergent() && !CalleeF->isConvergent() && - !CalleeF->isIntrinsic()) { - LLVM_DEBUG(dbgs() << "Removing convergent attr from instr " << Call - << "\n"); - Call.setNotConvergent(); - return &Call; - } - // If the call and callee calling conventions don't match, this call must // be unreachable, as the call is undefined. if (CalleeF->getCallingConv() != Call.getCallingConv() && Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -852,7 +852,7 @@ case Attribute::ArgMemOnly: case Attribute::Builtin: case Attribute::ByVal: - case Attribute::Convergent: + case Attribute::NoConvergent: case Attribute::Dereferenceable: case Attribute::DereferenceableOrNull: case Attribute::InAlloca: Index: llvm/test/Analysis/BasicAA/intrinsics.ll =================================================================== --- llvm/test/Analysis/BasicAA/intrinsics.ll +++ llvm/test/Analysis/BasicAA/intrinsics.ll @@ -22,6 +22,6 @@ declare <8 x i16> @llvm.masked.load.v8i16.p0v8i16(<8 x i16>*, i32, <8 x i1>, <8 x i16>) nounwind readonly declare void @llvm.masked.store.v8i16.p0v8i16(<8 x i16>, <8 x i16>*, i32, <8 x i1>) nounwind -; CHECK: attributes #0 = { argmemonly nounwind readonly willreturn } -; CHECK: attributes #1 = { argmemonly nounwind willreturn } +; CHECK: attributes #0 = { argmemonly noconvergent nounwind readonly willreturn } +; CHECK: attributes #1 = { argmemonly noconvergent nounwind willreturn } ; CHECK: attributes [[ATTR]] = { nounwind } Index: llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll =================================================================== --- llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll +++ llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -21,7 +21,7 @@ ret void } -; Add the readonly attribute, since there's just a call to a function which +; Add the readonly attribute, since there's just a call to a function which ; TBAA says doesn't modify any memory. ; CHECK: define void @test1_yes(i32* nocapture %p) #2 { @@ -49,7 +49,7 @@ ret void } -; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #3 { +; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #5 { define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind { call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i1 false), !tbaa !2 ret void @@ -63,7 +63,7 @@ ret i32 %t } -; CHECK: define i32 @test3_no(i8* nocapture %p) #5 { +; CHECK: define i32 @test3_no(i8* nocapture %p) #6 { define i32 @test3_no(i8* %p) nounwind { %t = va_arg i8* %p, i32, !tbaa !2 ret i32 %t @@ -72,13 +72,14 @@ declare void @callee(i32* %p) nounwind declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1) nounwind -; CHECK: attributes #0 = { norecurse nounwind readnone } -; CHECK: attributes #1 = { nofree norecurse nounwind writeonly } +; CHECK: attributes #0 = { noconvergent norecurse nounwind readnone } +; CHECK: attributes #1 = { noconvergent nofree norecurse nounwind writeonly } ; CHECK: attributes #2 = { nounwind readonly } ; CHECK: attributes #3 = { nounwind } -; CHECK: attributes #4 = { nounwind readnone } -; CHECK: attributes #5 = { nofree norecurse nounwind } -; CHECK: attributes #6 = { argmemonly nounwind willreturn } +; CHECK: attributes #4 = { noconvergent nounwind readnone } +; CHECK: attributes #5 = { noconvergent nounwind } +; CHECK: attributes #6 = { noconvergent nofree norecurse nounwind } +; CHECK: attributes #7 = { argmemonly noconvergent nounwind willreturn } ; Root note. !0 = !{ } Index: llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll =================================================================== --- llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll +++ llvm/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll @@ -22,8 +22,8 @@ declare <8 x i16> @llvm.masked.load.v8i16.p0v8i16(<8 x i16>*, i32, <8 x i1>, <8 x i16>) nounwind readonly declare void @llvm.masked.store.v8i16.p0v8i16(<8 x i16>, <8 x i16>*, i32, <8 x i1>) nounwind -; CHECK: attributes #0 = { argmemonly nounwind readonly willreturn } -; CHECK: attributes #1 = { argmemonly nounwind willreturn } +; CHECK: attributes #0 = { argmemonly noconvergent nounwind readonly willreturn } +; CHECK: attributes #1 = { argmemonly noconvergent nounwind willreturn } ; CHECK: attributes [[NUW]] = { nounwind } !0 = !{!"tbaa root"} Index: llvm/test/Assembler/invalid-noconvergent-argument.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-noconvergent-argument.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as -o /dev/null %s 2>&1 | FileCheck %s + +; CHECK: error: invalid use of function-only attribute +declare void @foo(i32 noconvergent) Index: llvm/test/Assembler/invalid-noconvergent-return.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/invalid-noconvergent-return.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as -o /dev/null %s 2>&1 | FileCheck %s + +; CHECK: error: invalid use of function-only attribute +declare noconvergent void @foo() Index: llvm/test/Bindings/llvm-c/debug_info.ll =================================================================== --- llvm/test/Bindings/llvm-c/debug_info.ll +++ llvm/test/Bindings/llvm-c/debug_info.ll @@ -12,13 +12,13 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata !41, metadata !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)), !dbg !44 ; CHECK-NEXT: } -; CHECK: ; Function Attrs: nounwind readnone speculatable +; CHECK: ; Function Attrs: noconvergent nounwind readnone speculatable ; CHECK-NEXT: declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 -; CHECK: ; Function Attrs: nounwind readnone speculatable +; CHECK: ; Function Attrs: noconvergent nounwind readnone speculatable ; CHECK-NEXT: declare void @llvm.dbg.value(metadata, metadata, metadata) #0 -; CHECK: attributes #0 = { nounwind readnone speculatable willreturn } +; CHECK: attributes #0 = { noconvergent nounwind readnone speculatable willreturn } ; CHECK: !llvm.dbg.cu = !{!0} ; CHECK-NEXT: !FooType = !{!28} Index: llvm/test/Bitcode/attributes.ll =================================================================== --- llvm/test/Bitcode/attributes.ll +++ llvm/test/Bitcode/attributes.ll @@ -251,13 +251,14 @@ ret i8* %foo } -; CHECK: define void @f43() #25 -define void @f43() convergent { +; convergent attribute removed +; CHECK: define void @f43() { +define void @f43() { ret void } define void @f44() argmemonly -; CHECK: define void @f44() #26 +; CHECK: define void @f44() #25 { ret void; } @@ -272,17 +273,17 @@ ret void } -; CHECK: define void @f47() #27 +; CHECK: define void @f47() #26 define void @f47() norecurse { ret void } -; CHECK: define void @f48() #28 +; CHECK: define void @f48() #27 define void @f48() inaccessiblememonly { ret void } -; CHECK: define void @f49() #29 +; CHECK: define void @f49() #28 define void @f49() inaccessiblemem_or_argmemonly { ret void } @@ -318,62 +319,67 @@ ret float 1.0 } -; CHECK: define i8* @f54(i32 %0) #30 +; CHECK: define i8* @f54(i32 %0) #29 define i8* @f54(i32 %0) allocsize(0) { ret i8* null } -; CHECK: define i8* @f55(i32 %0, i32 %1) #31 +; CHECK: define i8* @f55(i32 %0, i32 %1) #30 define i8* @f55(i32 %0, i32 %1) allocsize(0, 1) { ret i8* null } -; CHECK: define void @f56() #32 +; CHECK: define void @f56() #31 define void @f56() writeonly { ret void } -; CHECK: define void @f57() #33 +; CHECK: define void @f57() #32 define void @f57() speculatable { ret void } -; CHECK: define void @f58() #34 +; CHECK: define void @f58() #33 define void @f58() sanitize_hwaddress { ret void; } -; CHECK: define void @f59() #35 +; CHECK: define void @f59() #34 define void @f59() shadowcallstack { ret void } -; CHECK: define void @f60() #36 +; CHECK: define void @f60() #35 define void @f60() willreturn { ret void } -; CHECK: define void @f61() #37 +; CHECK: define void @f61() #36 define void @f61() nofree { ret void } -; CHECK: define void @f62() #38 +; CHECK: define void @f62() #37 define void @f62() nosync { ret void } -; CHECK: define void @f63() #39 +; CHECK: define void @f63() #38 define void @f63() sanitize_memtag { ret void; } +; CHECK: define void @f64() #39 +define void @f64() noconvergent { + ret void +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { readnone } @@ -399,19 +405,19 @@ ; CHECK: attributes #22 = { minsize } ; CHECK: attributes #23 = { noinline optnone } ; CHECK: attributes #24 = { jumptable } -; CHECK: attributes #25 = { convergent } -; CHECK: attributes #26 = { argmemonly } -; CHECK: attributes #27 = { norecurse } -; CHECK: attributes #28 = { inaccessiblememonly } -; CHECK: attributes #29 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #30 = { allocsize(0) } -; CHECK: attributes #31 = { allocsize(0,1) } -; CHECK: attributes #32 = { writeonly } -; CHECK: attributes #33 = { speculatable } -; CHECK: attributes #34 = { sanitize_hwaddress } -; CHECK: attributes #35 = { shadowcallstack } -; CHECK: attributes #36 = { willreturn } -; CHECK: attributes #37 = { nofree } -; CHECK: attributes #38 = { nosync } -; CHECK: attributes #39 = { sanitize_memtag } +; CHECK: attributes #25 = { argmemonly } +; CHECK: attributes #26 = { norecurse } +; CHECK: attributes #27 = { inaccessiblememonly } +; CHECK: attributes #28 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #29 = { allocsize(0) } +; CHECK: attributes #30 = { allocsize(0,1) } +; CHECK: attributes #31 = { writeonly } +; CHECK: attributes #32 = { speculatable } +; CHECK: attributes #33 = { sanitize_hwaddress } +; CHECK: attributes #34 = { shadowcallstack } +; CHECK: attributes #35 = { willreturn } +; CHECK: attributes #36 = { nofree } +; CHECK: attributes #37 = { nosync } +; CHECK: attributes #38 = { sanitize_memtag } +; CHECK: attributes #39 = { noconvergent } ; CHECK: attributes #40 = { nobuiltin } Index: llvm/test/Bitcode/compatibility-3.6.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.6.ll +++ llvm/test/Bitcode/compatibility-3.6.ll @@ -981,7 +981,7 @@ ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #35 + ; CHECK: call void @f.nobuiltin() #36 call fastcc noalias i32* @f.noalias() noinline ; CHECK: call fastcc noalias i32* @f.noalias() #11 @@ -1179,13 +1179,14 @@ ; CHECK: attributes #26 = { sspstrong } ; CHECK: attributes #27 = { uwtable } ; CHECK: attributes #28 = { "cpu"="cortex-a8" } -; CHECK: attributes #29 = { nounwind readnone willreturn } -; CHECK: attributes #30 = { argmemonly nounwind readonly } -; CHECK: attributes #31 = { argmemonly nounwind } -; CHECK: attributes #32 = { nounwind readnone } -; CHECK: attributes #33 = { nounwind readonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly nounwind willreturn } -; CHECK: attributes #35 = { builtin } +; CHECK: attributes #29 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #30 = { noconvergent nounwind } +; CHECK: attributes #31 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #32 = { argmemonly noconvergent nounwind } +; CHECK: attributes #33 = { noconvergent nounwind readnone } +; CHECK: attributes #34 = { nounwind readonly } +; CHECK: attributes #35 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } +; CHECK: attributes #36 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.7.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.7.ll +++ llvm/test/Bitcode/compatibility-3.7.ll @@ -443,62 +443,60 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 ; Functions -- section declare void @f.section() section "80" @@ -557,7 +555,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #32 +; CHECK: declare void @llvm.donothing() #31 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1025,9 +1023,9 @@ ; CHECK: call void @f.nobuiltin() #38 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1214,40 +1212,40 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { nounwind readnone willreturn } -; CHECK: attributes #33 = { argmemonly nounwind readonly } -; CHECK: attributes #34 = { argmemonly nounwind } -; CHECK: attributes #35 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #32 = { noconvergent nounwind } +; CHECK: attributes #33 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #34 = { argmemonly noconvergent nounwind } +; CHECK: attributes #35 = { noconvergent nounwind readnone } ; CHECK: attributes #36 = { nounwind readonly } -; CHECK: attributes #37 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #37 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #38 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.8.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.8.ll +++ llvm/test/Bitcode/compatibility-3.8.ll @@ -468,68 +468,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 ; Functions -- section declare void @f.section() section "80" @@ -588,7 +586,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1173,9 +1171,9 @@ ; CHECK: call void @f.nobuiltin() #41 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1521,43 +1519,43 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #41 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-3.9.ll =================================================================== --- llvm/test/Bitcode/compatibility-3.9.ll +++ llvm/test/Bitcode/compatibility-3.9.ll @@ -539,68 +539,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 ; Functions -- section declare void @f.section() section "80" @@ -659,7 +657,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1244,9 +1242,9 @@ ; CHECK: call void @f.nobuiltin() #42 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1594,44 +1592,44 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } ; CHECK: attributes #40 = { writeonly } -; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #42 = { builtin } ;; Metadata Index: llvm/test/Bitcode/compatibility-4.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-4.0.ll +++ llvm/test/Bitcode/compatibility-4.0.ll @@ -539,68 +539,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 ; Functions -- section declare void @f.section() section "80" @@ -659,7 +657,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1244,9 +1242,9 @@ ; CHECK: call void @f.nobuiltin() #42 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1619,46 +1617,47 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } ; CHECK: attributes #40 = { writeonly } -; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #41 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #42 = { builtin } + ;; Metadata ; Metadata -- Module flags Index: llvm/test/Bitcode/compatibility-5.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-5.0.ll +++ llvm/test/Bitcode/compatibility-5.0.ll @@ -543,68 +543,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 declare void @f.strictfp() #35 ; Functions -- section @@ -664,7 +662,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1254,9 +1252,9 @@ ; CHECK: call void @f.strictfp() #44 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1632,45 +1630,45 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } ; CHECK: attributes #40 = { writeonly } ; CHECK: attributes #41 = { speculatable } -; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #43 = { builtin } ; CHECK: attributes #44 = { strictfp } Index: llvm/test/Bitcode/compatibility-6.0.ll =================================================================== --- llvm/test/Bitcode/compatibility-6.0.ll +++ llvm/test/Bitcode/compatibility-6.0.ll @@ -550,68 +550,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 declare void @f.strictfp() #35 ; Functions -- section @@ -671,7 +669,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1265,9 +1263,9 @@ ; CHECK: call void @f.strictfp() #44 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1643,45 +1641,45 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } ; CHECK: attributes #40 = { writeonly } ; CHECK: attributes #41 = { speculatable } -; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #42 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #43 = { builtin } ; CHECK: attributes #44 = { strictfp } Index: llvm/test/Bitcode/compatibility.ll =================================================================== --- llvm/test/Bitcode/compatibility.ll +++ llvm/test/Bitcode/compatibility.ll @@ -564,68 +564,66 @@ ; CHECK: declare void @f.alwaysinline() #2 declare void @f.cold() cold ; CHECK: declare void @f.cold() #3 -declare void @f.convergent() convergent -; CHECK: declare void @f.convergent() #4 declare void @f.inlinehint() inlinehint -; CHECK: declare void @f.inlinehint() #5 +; CHECK: declare void @f.inlinehint() #4 declare void @f.jumptable() unnamed_addr jumptable -; CHECK: declare void @f.jumptable() unnamed_addr #6 +; CHECK: declare void @f.jumptable() unnamed_addr #5 declare void @f.minsize() minsize -; CHECK: declare void @f.minsize() #7 +; CHECK: declare void @f.minsize() #6 declare void @f.naked() naked -; CHECK: declare void @f.naked() #8 +; CHECK: declare void @f.naked() #7 declare void @f.nobuiltin() nobuiltin -; CHECK: declare void @f.nobuiltin() #9 +; CHECK: declare void @f.nobuiltin() #8 declare void @f.noduplicate() noduplicate -; CHECK: declare void @f.noduplicate() #10 +; CHECK: declare void @f.noduplicate() #9 declare void @f.noimplicitfloat() noimplicitfloat -; CHECK: declare void @f.noimplicitfloat() #11 +; CHECK: declare void @f.noimplicitfloat() #10 declare void @f.noinline() noinline -; CHECK: declare void @f.noinline() #12 +; CHECK: declare void @f.noinline() #11 declare void @f.nonlazybind() nonlazybind -; CHECK: declare void @f.nonlazybind() #13 +; CHECK: declare void @f.nonlazybind() #12 declare void @f.noredzone() noredzone -; CHECK: declare void @f.noredzone() #14 +; CHECK: declare void @f.noredzone() #13 declare void @f.noreturn() noreturn -; CHECK: declare void @f.noreturn() #15 +; CHECK: declare void @f.noreturn() #14 declare void @f.nounwind() nounwind -; CHECK: declare void @f.nounwind() #16 +; CHECK: declare void @f.nounwind() #15 declare void @f.optnone() noinline optnone -; CHECK: declare void @f.optnone() #17 +; CHECK: declare void @f.optnone() #16 declare void @f.optsize() optsize -; CHECK: declare void @f.optsize() #18 +; CHECK: declare void @f.optsize() #17 declare void @f.readnone() readnone -; CHECK: declare void @f.readnone() #19 +; CHECK: declare void @f.readnone() #18 declare void @f.readonly() readonly -; CHECK: declare void @f.readonly() #20 +; CHECK: declare void @f.readonly() #19 declare void @f.returns_twice() returns_twice -; CHECK: declare void @f.returns_twice() #21 +; CHECK: declare void @f.returns_twice() #20 declare void @f.safestack() safestack -; CHECK: declare void @f.safestack() #22 +; CHECK: declare void @f.safestack() #21 declare void @f.sanitize_address() sanitize_address -; CHECK: declare void @f.sanitize_address() #23 +; CHECK: declare void @f.sanitize_address() #22 declare void @f.sanitize_memory() sanitize_memory -; CHECK: declare void @f.sanitize_memory() #24 +; CHECK: declare void @f.sanitize_memory() #23 declare void @f.sanitize_thread() sanitize_thread -; CHECK: declare void @f.sanitize_thread() #25 +; CHECK: declare void @f.sanitize_thread() #24 declare void @f.ssp() ssp -; CHECK: declare void @f.ssp() #26 +; CHECK: declare void @f.ssp() #25 declare void @f.sspreq() sspreq -; CHECK: declare void @f.sspreq() #27 +; CHECK: declare void @f.sspreq() #26 declare void @f.sspstrong() sspstrong -; CHECK: declare void @f.sspstrong() #28 +; CHECK: declare void @f.sspstrong() #27 declare void @f.thunk() "thunk" -; CHECK: declare void @f.thunk() #29 +; CHECK: declare void @f.thunk() #28 declare void @f.uwtable() uwtable -; CHECK: declare void @f.uwtable() #30 +; CHECK: declare void @f.uwtable() #29 declare void @f.kvpair() "cpu"="cortex-a8" -; CHECK:declare void @f.kvpair() #31 +; CHECK:declare void @f.kvpair() #30 declare void @f.norecurse() norecurse -; CHECK: declare void @f.norecurse() #32 +; CHECK: declare void @f.norecurse() #31 declare void @f.inaccessiblememonly() inaccessiblememonly -; CHECK: declare void @f.inaccessiblememonly() #33 +; CHECK: declare void @f.inaccessiblememonly() #32 declare void @f.inaccessiblemem_or_argmemonly() inaccessiblemem_or_argmemonly -; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #34 +; CHECK: declare void @f.inaccessiblemem_or_argmemonly() #33 declare void @f.strictfp() #35 ; Functions -- section @@ -691,7 +689,7 @@ ; Functions -- Personality constant declare void @llvm.donothing() nounwind readnone -; CHECK: declare void @llvm.donothing() #35 +; CHECK: declare void @llvm.donothing() #34 define void @f.no_personality() personality i8 3 { ; CHECK: define void @f.no_personality() personality i8 3 invoke void @llvm.donothing() to label %normal unwind label %exception @@ -1396,9 +1394,9 @@ ; CHECK: call void @f.nobuiltin() #44 call fastcc noalias i32* @f.noalias() noinline - ; CHECK: call fastcc noalias i32* @f.noalias() #12 + ; CHECK: call fastcc noalias i32* @f.noalias() #11 tail call ghccc nonnull i32* @f.nonnull() minsize - ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #7 + ; CHECK: tail call ghccc nonnull i32* @f.nonnull() #6 ret void } @@ -1794,48 +1792,49 @@ ; CHECK: attributes #1 = { alignstack=8 } ; CHECK: attributes #2 = { alwaysinline } ; CHECK: attributes #3 = { cold } -; CHECK: attributes #4 = { convergent } -; CHECK: attributes #5 = { inlinehint } -; CHECK: attributes #6 = { jumptable } -; CHECK: attributes #7 = { minsize } -; CHECK: attributes #8 = { naked } -; CHECK: attributes #9 = { nobuiltin } -; CHECK: attributes #10 = { noduplicate } -; CHECK: attributes #11 = { noimplicitfloat } -; CHECK: attributes #12 = { noinline } -; CHECK: attributes #13 = { nonlazybind } -; CHECK: attributes #14 = { noredzone } -; CHECK: attributes #15 = { noreturn } -; CHECK: attributes #16 = { nounwind } -; CHECK: attributes #17 = { noinline optnone } -; CHECK: attributes #18 = { optsize } -; CHECK: attributes #19 = { readnone } -; CHECK: attributes #20 = { readonly } -; CHECK: attributes #21 = { returns_twice } -; CHECK: attributes #22 = { safestack } -; CHECK: attributes #23 = { sanitize_address } -; CHECK: attributes #24 = { sanitize_memory } -; CHECK: attributes #25 = { sanitize_thread } -; CHECK: attributes #26 = { ssp } -; CHECK: attributes #27 = { sspreq } -; CHECK: attributes #28 = { sspstrong } -; CHECK: attributes #29 = { "thunk" } -; CHECK: attributes #30 = { uwtable } -; CHECK: attributes #31 = { "cpu"="cortex-a8" } -; CHECK: attributes #32 = { norecurse } -; CHECK: attributes #33 = { inaccessiblememonly } -; CHECK: attributes #34 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #35 = { nounwind readnone willreturn } -; CHECK: attributes #36 = { argmemonly nounwind readonly } -; CHECK: attributes #37 = { argmemonly nounwind } -; CHECK: attributes #38 = { nounwind readnone } +; CHECK: attributes #4 = { inlinehint } +; CHECK: attributes #5 = { jumptable } +; CHECK: attributes #6 = { minsize } +; CHECK: attributes #7 = { naked } +; CHECK: attributes #8 = { nobuiltin } +; CHECK: attributes #9 = { noduplicate } +; CHECK: attributes #10 = { noimplicitfloat } +; CHECK: attributes #11 = { noinline } +; CHECK: attributes #12 = { nonlazybind } +; CHECK: attributes #13 = { noredzone } +; CHECK: attributes #14 = { noreturn } +; CHECK: attributes #15 = { nounwind } +; CHECK: attributes #16 = { noinline optnone } +; CHECK: attributes #17 = { optsize } +; CHECK: attributes #18 = { readnone } +; CHECK: attributes #19 = { readonly } +; CHECK: attributes #20 = { returns_twice } +; CHECK: attributes #21 = { safestack } +; CHECK: attributes #22 = { sanitize_address } +; CHECK: attributes #23 = { sanitize_memory } +; CHECK: attributes #24 = { sanitize_thread } +; CHECK: attributes #25 = { ssp } +; CHECK: attributes #26 = { sspreq } +; CHECK: attributes #27 = { sspstrong } +; CHECK: attributes #28 = { "thunk" } +; CHECK: attributes #29 = { uwtable } +; CHECK: attributes #30 = { "cpu"="cortex-a8" } +; CHECK: attributes #31 = { norecurse } +; CHECK: attributes #32 = { inaccessiblememonly } +; CHECK: attributes #33 = { inaccessiblemem_or_argmemonly } +; CHECK: attributes #34 = { noconvergent nounwind readnone willreturn } +; CHECK: attributes #35 = { noconvergent nounwind } +; CHECK: attributes #36 = { argmemonly noconvergent nounwind readonly } +; CHECK: attributes #37 = { argmemonly noconvergent nounwind } +; CHECK: attributes #38 = { noconvergent nounwind readnone } ; CHECK: attributes #39 = { nounwind readonly } -; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly nounwind willreturn } +; CHECK: attributes #40 = { inaccessiblemem_or_argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #41 = { writeonly } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { strictfp } ; CHECK: attributes #44 = { builtin } + ;; Metadata ; Metadata -- Module flags Index: llvm/test/Bitcode/convergent-upgrade.ll =================================================================== --- /dev/null +++ llvm/test/Bitcode/convergent-upgrade.ll @@ -0,0 +1,29 @@ +; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: verify-uselistorder < %s.bc + +; Make sure the convergent attribute is dropped. + +; convergent-upgrade.ll.bc was produced by running a version of llvm-as from just +; before the IR change on this file. + +; No attributes +; CHECK: define void @test_convergent_fn() { +define void @test_convergent_fn() #0 { + ret void +} + +; CHECK: declare void @test_convergent_extern(){{$}} +declare void @test_convergent_extern() #0 + +; CHECK: declare void @extern(){{$}} +declare void @extern() + +define void @test_convergent_callsize() { + ; CHECK: call void @extern(){{$}} + call void @extern() #0 + ret void +} + +; CHECK-NOT: attributes + +attributes #0 = { convergent } Index: llvm/test/Bitcode/ptest-new.ll =================================================================== --- llvm/test/Bitcode/ptest-new.ll +++ llvm/test/Bitcode/ptest-new.ll @@ -23,4 +23,4 @@ declare i32 @llvm.x86.sse41.ptestnzc(<2 x i64>, <2 x i64>) nounwind readnone ; CHECK: attributes #0 = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { noconvergent nounwind readnone } Index: llvm/test/Bitcode/ptest-old.ll =================================================================== --- llvm/test/Bitcode/ptest-old.ll +++ llvm/test/Bitcode/ptest-old.ll @@ -6,7 +6,7 @@ entry: ; CHECK: call i32 @llvm.x86.sse41.ptestc(<2 x i64> %res1 = call i32 @llvm.x86.sse41.ptestc(<4 x float> %bar, <4 x float> %bar) -; CHECK: call i32 @llvm.x86.sse41.ptestz(<2 x i64> +; CHECK: call i32 @llvm.x86.sse41.ptestz(<2 x i64> %res2 = call i32 @llvm.x86.sse41.ptestz(<4 x float> %bar, <4 x float> %bar) ; CHECK: call i32 @llvm.x86.sse41.ptestnzc(<2 x i64> %res3 = call i32 @llvm.x86.sse41.ptestnzc(<4 x float> %bar, <4 x float> %bar) @@ -24,4 +24,4 @@ declare i32 @llvm.x86.sse41.ptestnzc(<4 x float>, <4 x float>) nounwind readnone ; CHECK: attributes #0 = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { noconvergent nounwind readnone } Index: llvm/test/Bitcode/upgrade-invariant-group-barrier.ll =================================================================== --- llvm/test/Bitcode/upgrade-invariant-group-barrier.ll +++ llvm/test/Bitcode/upgrade-invariant-group-barrier.ll @@ -13,9 +13,9 @@ ret void } -; CHECK: Function Attrs: inaccessiblememonly nounwind speculatable +; CHECK: Function Attrs: inaccessiblememonly noconvergent nounwind speculatable ; CHECK: declare i8* @llvm.launder.invariant.group.p0i8(i8*) -; CHECK: Function Attrs: inaccessiblememonly nounwind speculatable +; CHECK: Function Attrs: inaccessiblememonly noconvergent nounwind speculatable ; CHECK: declare i16* @llvm.launder.invariant.group.p0i16(i16*) declare i8* @llvm.invariant.group.barrier(i8*) declare i8* @llvm.invariant.group.barrier.p0i8(i8*) Index: llvm/test/CodeGen/AMDGPU/buffer-intrinsics-mmo-offsets.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/buffer-intrinsics-mmo-offsets.ll +++ llvm/test/CodeGen/AMDGPU/buffer-intrinsics-mmo-offsets.ll @@ -15,27 +15,27 @@ ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 16, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_DWORDX4_OFFEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 16, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[BUFFER_LOAD_DWORDX4_OFFSET]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 32, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 32, align 1, addrspace 4) ; GCN: BUFFER_STORE_DWORDX4_OFFEN_exact killed [[BUFFER_LOAD_DWORDX4_OFFEN]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 32, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 32, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFSET [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 48, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 48, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 48, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 48, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFSET_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFSET]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 64, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 64, align 1, addrspace 4) ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFEN_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFEN]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_FORMAT_XYZW_IDXEN_exact killed [[BUFFER_LOAD_FORMAT_XYZW_IDXEN]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 64, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_FORMAT_XYZW_IDXEN_exact killed [[BUFFER_LOAD_FORMAT_XYZW_IDXEN1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 64, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_ATOMIC_ADD_OFFSET [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 80, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 80, align 1, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_OFFEN [[COPY]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 80, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 80, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY]], %subreg.sub1 ; GCN: [[DEF:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_OFFSET [[REG_SEQUENCE1]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 96, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 96, align 1, addrspace 4) @@ -49,13 +49,13 @@ ; GCN: [[DEF3:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_IDXEN [[REG_SEQUENCE1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 96, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[DEF3]].sub0 - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 1065353216, implicit $exec ; GCN: BUFFER_ATOMIC_ADD_F32_OFFSET [[V_MOV_B32_e32_1]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 112, 0, implicit $exec :: (load store 4 on custom TargetCustom7 + 112, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_F32_OFFEN [[V_MOV_B32_e32_1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 0, 0, implicit $exec :: (load store 4 on custom TargetCustom7, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_F32_IDXEN [[V_MOV_B32_e32_1]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 112, 0, implicit $exec :: (load store 4 on custom TargetCustom7, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_F32_IDXEN [[V_MOV_B32_e32_1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 112, 0, implicit $exec :: (load store 4 on custom TargetCustom7, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[BUFFER_LOAD_DWORDX4_OFFSET1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 128, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 128, align 1, addrspace 4) ; GCN: [[S_MOV_B32_1:%[0-9]+]]:sreg_32 = S_MOV_B32 64 ; GCN: [[BUFFER_LOAD_DWORDX4_OFFSET2:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[S_LOAD_DWORDX4_IMM]], killed [[S_MOV_B32_1]], 64, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 128, align 1, addrspace 4) @@ -64,7 +64,7 @@ ; GCN: [[BUFFER_LOAD_DWORDX4_OFFEN1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_2]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY6:%[0-9]+]]:sreg_32 = COPY [[COPY]] ; GCN: [[BUFFER_LOAD_DWORDX4_OFFSET4:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[S_LOAD_DWORDX4_IMM]], [[COPY6]], 128, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFSET1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFSET [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 144, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 144, align 1, addrspace 4) ; GCN: [[S_MOV_B32_3:%[0-9]+]]:sreg_32 = S_MOV_B32 72 ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFSET2:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFSET [[S_LOAD_DWORDX4_IMM]], killed [[S_MOV_B32_3]], 72, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 144, align 1, addrspace 4) @@ -73,7 +73,7 @@ ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFEN1:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_4]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY7:%[0-9]+]]:sreg_32 = COPY [[COPY]] ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_OFFSET4:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_OFFSET [[S_LOAD_DWORDX4_IMM]], [[COPY7]], 144, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_ATOMIC_ADD_OFFSET [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 160, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 160, align 1, addrspace 4) ; GCN: [[S_MOV_B32_5:%[0-9]+]]:sreg_32 = S_MOV_B32 80 ; GCN: BUFFER_ATOMIC_ADD_OFFSET [[COPY]], [[S_LOAD_DWORDX4_IMM]], killed [[S_MOV_B32_5]], 80, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 160, align 1, addrspace 4) @@ -82,7 +82,7 @@ ; GCN: BUFFER_ATOMIC_ADD_OFFEN [[COPY]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_6]], 0, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY8:%[0-9]+]]:sreg_32 = COPY [[COPY]] ; GCN: BUFFER_ATOMIC_ADD_OFFSET [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[COPY8]], 160, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[DEF4:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_OFFSET [[REG_SEQUENCE1]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 176, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 176, align 1, addrspace 4) ; GCN: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[DEF4]].sub0 @@ -101,7 +101,7 @@ ; GCN: [[DEF8:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_OFFSET [[REG_SEQUENCE1]], [[S_LOAD_DWORDX4_IMM]], [[COPY13]], 176, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY14:%[0-9]+]]:vgpr_32 = COPY [[DEF8]].sub0 - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[BUFFER_LOAD_DWORDX4_OFFSET1]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 192, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 192, align 1, addrspace 4) ; GCN: [[S_MOV_B32_9:%[0-9]+]]:sreg_32 = S_MOV_B32 96 ; GCN: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[BUFFER_LOAD_DWORDX4_OFFSET2]], [[S_LOAD_DWORDX4_IMM]], killed [[S_MOV_B32_9]], 96, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 192, align 1, addrspace 4) @@ -110,7 +110,7 @@ ; GCN: BUFFER_STORE_DWORDX4_OFFEN_exact killed [[BUFFER_LOAD_DWORDX4_OFFEN1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_10]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY15:%[0-9]+]]:sreg_32 = COPY [[COPY]] ; GCN: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[BUFFER_LOAD_DWORDX4_OFFSET4]], [[S_LOAD_DWORDX4_IMM]], [[COPY15]], 192, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFSET_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFSET1]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 208, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 208, align 1, addrspace 4) ; GCN: [[S_MOV_B32_11:%[0-9]+]]:sreg_32 = S_MOV_B32 104 ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFSET_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFSET2]], [[S_LOAD_DWORDX4_IMM]], killed [[S_MOV_B32_11]], 104, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 208, align 1, addrspace 4) @@ -119,7 +119,7 @@ ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFEN_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFEN1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_12]], 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY16:%[0-9]+]]:sreg_32 = COPY [[COPY]] ; GCN: BUFFER_STORE_FORMAT_XYZW_OFFSET_exact killed [[BUFFER_LOAD_FORMAT_XYZW_OFFSET4]], [[S_LOAD_DWORDX4_IMM]], [[COPY16]], 208, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY17:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN2:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY17]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 224, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 224, align 1, addrspace 4) ; GCN: [[S_MOV_B32_13:%[0-9]+]]:sreg_32 = S_MOV_B32 112 @@ -135,7 +135,7 @@ ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN5:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY20]], [[S_LOAD_DWORDX4_IMM]], [[COPY21]], 224, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN6:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 224, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_DWORDX4_IDXEN7:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 224, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY22:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN2:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[COPY22]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 240, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7 + 240, align 1, addrspace 4) ; GCN: [[S_MOV_B32_15:%[0-9]+]]:sreg_32 = S_MOV_B32 120 @@ -150,7 +150,7 @@ ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN5:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[COPY25]], [[S_LOAD_DWORDX4_IMM]], [[COPY26]], 240, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN6:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 240, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) ; GCN: [[BUFFER_LOAD_FORMAT_XYZW_IDXEN7:%[0-9]+]]:vreg_128 = BUFFER_LOAD_FORMAT_XYZW_IDXEN [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 240, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load 16 from custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY27:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[COPY27]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 256, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 256, align 1, addrspace 4) ; GCN: [[COPY28:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] @@ -164,7 +164,7 @@ ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[COPY30]], [[S_LOAD_DWORDX4_IMM]], [[COPY31]], 256, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 256, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_ATOMIC_ADD_IDXEN [[COPY]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 256, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY32:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: [[DEF9:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_IDXEN [[REG_SEQUENCE1]], [[COPY32]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 272, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7 + 272, align 1, addrspace 4) @@ -193,7 +193,7 @@ ; GCN: [[DEF15:%[0-9]+]]:vreg_64 = IMPLICIT_DEF ; GCN: BUFFER_ATOMIC_CMPSWAP_IDXEN [[REG_SEQUENCE1]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 272, 0, implicit $exec :: (volatile dereferenceable load store 4 on custom TargetCustom7, align 1, addrspace 4) ; GCN: [[COPY43:%[0-9]+]]:vgpr_32 = COPY [[DEF15]].sub0 - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY44:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN2]], [[COPY44]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 288, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 288, align 1, addrspace 4) ; GCN: [[COPY45:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] @@ -207,7 +207,7 @@ ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN5]], [[COPY47]], [[S_LOAD_DWORDX4_IMM]], [[COPY48]], 288, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN6]], [[V_MOV_B32_e32_]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 288, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) ; GCN: BUFFER_STORE_DWORDX4_IDXEN_exact killed [[BUFFER_LOAD_DWORDX4_IDXEN7]], [[COPY]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 288, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7, align 1, addrspace 4) - ; GCN: INLINEASM &"", 1 + ; GCN: INLINEASM &"", 33 ; GCN: [[COPY49:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_]] ; GCN: BUFFER_STORE_FORMAT_XYZW_IDXEN_exact killed [[BUFFER_LOAD_FORMAT_XYZW_IDXEN2]], [[COPY49]], [[S_LOAD_DWORDX4_IMM]], [[S_MOV_B32_]], 304, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable store 16 into custom TargetCustom7 + 304, align 1, addrspace 4) ; GCN: [[S_MOV_B32_21:%[0-9]+]]:sreg_32 = S_MOV_B32 152 Index: llvm/test/CodeGen/AMDGPU/convergent-inlineasm.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/convergent-inlineasm.ll +++ llvm/test/CodeGen/AMDGPU/convergent-inlineasm.ll @@ -9,7 +9,7 @@ define amdgpu_kernel void @convergent_inlineasm(i64 addrspace(1)* nocapture %arg) { bb: %tmp = call i32 @llvm.amdgcn.workitem.id.x() - %tmp1 = tail call i64 asm "v_cmp_ne_u32_e64 $0, 0, $1", "=s,v"(i32 1) #1 + %tmp1 = tail call i64 asm "v_cmp_ne_u32_e64 $0, 0, $1", "=s,v"(i32 1) %tmp2 = icmp eq i32 %tmp, 8 br i1 %tmp2, label %bb3, label %bb5 @@ -33,7 +33,7 @@ define amdgpu_kernel void @nonconvergent_inlineasm(i64 addrspace(1)* nocapture %arg) { bb: %tmp = call i32 @llvm.amdgcn.workitem.id.x() - %tmp1 = tail call i64 asm "v_cmp_ne_u32_e64 $0, 0, $1", "=s,v"(i32 1) + %tmp1 = tail call i64 asm "v_cmp_ne_u32_e64 $0, 0, $1", "=s,v"(i32 1) #0 %tmp2 = icmp eq i32 %tmp, 8 br i1 %tmp2, label %bb3, label %bb5 @@ -46,5 +46,4 @@ ret void } -attributes #0 = { nounwind readnone } -attributes #1 = { convergent nounwind readnone } +attributes #0 = { noconvergent } Index: llvm/test/CodeGen/AMDGPU/lds-output-queue.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/lds-output-queue.ll +++ llvm/test/CodeGen/AMDGPU/lds-output-queue.ll @@ -23,7 +23,7 @@ ret void } -declare void @llvm.r600.group.barrier() nounwind convergent +declare void @llvm.r600.group.barrier() nounwind ; The machine scheduler does not do proper alias analysis and assumes that ; loads from global values (Note that a global value is different that a Index: llvm/test/CodeGen/AMDGPU/llvm.amdgcn.init.exec.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/llvm.amdgcn.init.exec.ll +++ llvm/test/CodeGen/AMDGPU/llvm.amdgcn.init.exec.ll @@ -84,7 +84,5 @@ unreachable } -declare void @llvm.amdgcn.init.exec(i64) #1 -declare void @llvm.amdgcn.init.exec.from.input(i32, i32) #1 - -attributes #1 = { convergent } +declare void @llvm.amdgcn.init.exec(i64) +declare void @llvm.amdgcn.init.exec.from.input(i32, i32) Index: llvm/test/CodeGen/AMDGPU/schedule-vs-if-nested-loop-failure.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/schedule-vs-if-nested-loop-failure.ll +++ llvm/test/CodeGen/AMDGPU/schedule-vs-if-nested-loop-failure.ll @@ -1,7 +1,7 @@ ; RUN: llc -O0 -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s ; RUN: llc -O0 -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s -declare void @llvm.amdgcn.s.barrier() nounwind convergent +declare void @llvm.amdgcn.s.barrier() nounwind ; GCN-LABEL: {{^}}main: define amdgpu_vs void @main(<4 x float> inreg %reg0, <4 x float> inreg %reg1) { Index: llvm/test/CodeGen/Mips/micromips-b-range.ll =================================================================== --- llvm/test/CodeGen/Mips/micromips-b-range.ll +++ llvm/test/CodeGen/Mips/micromips-b-range.ll @@ -72,26 +72,26 @@ ] lb: - tail call void asm sideeffect ".space 0", ""() + tail call void asm sideeffect ".space 0", ""() noconvergent br label %le lc: - tail call void asm sideeffect ".space 0", ""() + tail call void asm sideeffect ".space 0", ""() noconvergent br label %le le: - tail call void asm sideeffect ".space 66500", ""() + tail call void asm sideeffect ".space 66500", ""() noconvergent br label %lg lf: - tail call void asm sideeffect ".space 0", ""() + tail call void asm sideeffect ".space 0", ""() noconvergent br label %lg lg: - tail call void asm sideeffect ".space 0", ""() + tail call void asm sideeffect ".space 0", ""() noconvergent br label %li li: - tail call void asm sideeffect ".space 0", ""() + tail call void asm sideeffect ".space 0", ""() noconvergent ret void } Index: llvm/test/CodeGen/NVPTX/convergent-mir-call.ll =================================================================== --- llvm/test/CodeGen/NVPTX/convergent-mir-call.ll +++ llvm/test/CodeGen/NVPTX/convergent-mir-call.ll @@ -5,8 +5,8 @@ target triple = "nvptx64-nvidia-cuda" -declare void @conv() convergent -declare void @not_conv() +declare void @conv() +declare void @not_conv() noconvergent define void @test(void ()* %f) { ; CHECK: ConvergentCallUniPrintCall @@ -18,10 +18,10 @@ call void @not_conv() ; CHECK: ConvergentCallPrintCall - call void %f() convergent + call void %f() ; CHECK: CallPrintCall - call void %f() + call void %f() noconvergent ret void } Index: llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll =================================================================== --- llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll +++ llvm/test/CodeGen/X86/inline-asm-avx512f-x-constraint.ll @@ -6,6 +6,6 @@ define <8 x i64> @mask_Yk_i8(i8 signext %msk, <8 x i64> %x, <8 x i64> %y) { entry: - %0 = tail call <8 x i64> asm "vpaddq\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i8 %msk, <8 x i64> %x, <8 x i64> %y) + %0 = tail call <8 x i64> asm "vpaddq\09$3, $2, $0 {$1}", "=x,^Yk,x,x,~{dirflag},~{fpsr},~{flags}"(i8 %msk, <8 x i64> %x, <8 x i64> %y) noconvergent ret <8 x i64> %0 } Index: llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll =================================================================== --- llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll +++ llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll @@ -3,6 +3,6 @@ ; CHECK: INLINEASM &"", 1, 12, implicit-def early-clobber $df, 12, implicit-def early-clobber $fpsw, 12, implicit-def early-clobber $eflags define void @foo() { entry: - call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() noconvergent ret void } Index: llvm/test/Feature/intrinsics.ll =================================================================== --- llvm/test/Feature/intrinsics.ll +++ llvm/test/Feature/intrinsics.ll @@ -69,5 +69,5 @@ ret void } -; CHECK: attributes #0 = { nounwind readnone speculatable willreturn } -; CHECK: attributes #1 = { cold noreturn nounwind } +; CHECK: attributes #0 = { noconvergent nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { cold noconvergent noreturn nounwind } Index: llvm/test/Other/invariant.group.ll =================================================================== --- llvm/test/Other/invariant.group.ll +++ llvm/test/Other/invariant.group.ll @@ -92,13 +92,13 @@ declare void @useBool(i1) declare void @clobber(i8*) -; CHECK: Function Attrs: inaccessiblememonly nounwind speculatable willreturn{{$}} +; CHECK: Function Attrs: inaccessiblememonly noconvergent nounwind speculatable willreturn{{$}} ; CHECK-NEXT: declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8* @llvm.launder.invariant.group.p0i8(i8*) -; CHECK: Function Attrs: nounwind readnone speculatable willreturn{{$}} +; CHECK: Function Attrs: noconvergent nounwind readnone speculatable willreturn{{$}} ; CHECK-NEXT: declare i8* @llvm.strip.invariant.group.p0i8(i8*) declare i8* @llvm.strip.invariant.group.p0i8(i8*) -!0 = !{} \ No newline at end of file +!0 = !{} Index: llvm/test/TableGen/intrin-side-effects.td =================================================================== --- llvm/test/TableGen/intrin-side-effects.td +++ llvm/test/TableGen/intrin-side-effects.td @@ -36,4 +36,4 @@ // CHECK: 1, // llvm.random.gen // CHECK: case 1: -// CHECK-NEXT: Atts[] = {Attribute::NoUnwind} +// CHECK-NEXT: Atts[] = {Attribute::NoUnwind,Attribute::NoConvergent} Index: llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll @@ -205,7 +205,7 @@ ; CHECK-LABEL: Tail: ; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ] ; CHECK: ret i32 %[[MERGED]] -define i32 @callee(i32* %a, i32 %v, i32 %p) { +define i32 @callee(i32* %a, i32 %v, i32 %p) noconvergent { ret i32 0 } @@ -244,10 +244,10 @@ ; CHECK-NEXT: %l = phi i32 [ %l1, %Header.split ], [ %l2, %TBB.split ] ; CHECK: call void @bari(i32 %l) -define void @bar(i32*, i32) { +define void @bar(i32*, i32) noconvergent { ret void } -define void @bari(i32) { +define void @bari(i32) noconvergent { ret void } Index: llvm/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll @@ -134,6 +134,6 @@ ret i32 %v } -define i32 @callee(i32* %a, i32 %v, i32 %p) { +define i32 @callee(i32* %a, i32 %v, i32 %p) noconvergent { ret i32 10 } Index: llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -callsite-splitting -o - < %s | FileCheck %s ; RUN: opt -S -strip-debug -callsite-splitting -o - < %s | FileCheck %s -define internal i16 @bar(i16 %p1, i16 %p2) { +define internal i16 @bar(i16 %p1, i16 %p2) noconvergent { %_tmp3 = mul i16 %p2, %p1 ret i16 %_tmp3 } Index: llvm/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll @@ -381,7 +381,7 @@ br i1 %tobool1, label %Tail, label %TBB TBB: - %cmp = icmp eq i32 %v, %v2 + %cmp = icmp eq i32 %v, %v2 br i1 %cmp, label %Tail, label %End Tail: @@ -428,7 +428,7 @@ br i1 %tobool1, label %Tail, label %TBB TBB: - %cmp = icmp eq i32 %v, %v2 + %cmp = icmp eq i32 %v, %v2 br i1 %cmp, label %Tail, label %End Tail: @@ -538,7 +538,7 @@ ret i32 %v } -define i32 @callee(i32* %a, i32 %v, i32 %p) { +define i32 @callee(i32* %a, i32 %v, i32 %p) noconvergent { entry: %c = icmp ne i32* %a, null br i1 %c, label %BB1, label %BB2 @@ -555,8 +555,8 @@ ret i32 %p } -declare void @dummy(i32*, i32) -declare void @dummy2(i32, i32) +declare void @dummy(i32*, i32) noconvergent +declare void @dummy2(i32, i32) noconvergent ; Make sure we remove the non-nullness on constant paramater. ; @@ -568,7 +568,7 @@ br label %Top0 Top0: - %tobool1 = icmp eq i32* %a_elt, inttoptr (i64 4643 to i32*) + %tobool1 = icmp eq i32* %a_elt, inttoptr (i64 4643 to i32*) br i1 %tobool1, label %Top1, label %NextCond Top1: Index: llvm/test/Transforms/CallSiteSplitting/callsite-split-preserve-debug.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-split-preserve-debug.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-split-preserve-debug.ll @@ -46,7 +46,7 @@ ret void } -define i32 @callee(i32 %aa, i32 %bb) { +define i32 @callee(i32 %aa, i32 %bb) noconvergent { entry: %add = add nsw i32 %aa, %bb ret i32 %add Index: llvm/test/Transforms/CallSiteSplitting/callsite-split.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/callsite-split.ll +++ llvm/test/Transforms/CallSiteSplitting/callsite-split.ll @@ -35,7 +35,7 @@ ret void } -define void @callee(%struct.bitmap* %dst_elt, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, i1 %c) { +define void @callee(%struct.bitmap* %dst_elt, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, i1 %c) noconvergent { entry: %tobool = icmp ne %struct.bitmap* %a_elt, null %tobool1 = icmp ne %struct.bitmap* %b_elt, null @@ -98,7 +98,7 @@ ret void } -define i1 @callee2(i1 %b) { +define i1 @callee2(i1 %b) noconvergent { entry: br i1 %b, label %BB1, label %BB2 @@ -114,6 +114,6 @@ ret i1 %b } -declare void @dummy3() -declare void @dummy4() -declare void @foo(i1) +declare void @dummy3() noconvergent +declare void @dummy4() noconvergent +declare void @foo(i1) noconvergent Index: llvm/test/Transforms/CallSiteSplitting/convergent.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/convergent.ll +++ llvm/test/Transforms/CallSiteSplitting/convergent.ll @@ -43,8 +43,8 @@ ; Make sure an otherwise identical function is transformed ; CHECK-LABEL: define void @reference_caller( -; CHECK: call void @nonconvergent_callee( -; CHECK: call void @nonconvergent_callee( +; CHECK: call void @noconvergent_callee( +; CHECK: call void @noconvergent_callee( define void @reference_caller(i1 %c, i8* %a_elt, i8* %b_elt) #1 { entry: br label %Top @@ -59,17 +59,17 @@ CallSiteBB: %p = phi i1 [ false, %Top ], [ %c, %NextCond ] - call void @nonconvergent_callee(i8* %a_elt, i1 %p) + call void @noconvergent_callee(i8* %a_elt, i1 %p) br label %End End: ret void } -; CHECK-LABEL: define void @nonconvergent_callee( -; CHECK: call void @nonconvergent_external( -; CHECK-NOT: call void @nonconvergent_external( -define void @nonconvergent_callee(i8* %a_elt, i1 %c) #1 { +; CHECK-LABEL: define void @noconvergent_callee( +; CHECK: call void @noconvergent_external( +; CHECK-NOT: call void @noconvergent_external( +define void @noconvergent_callee(i8* %a_elt, i1 %c) #1 { entry: %tobool = icmp ne i8* %a_elt, null br i1 %tobool, label %then, label %endif @@ -78,12 +78,12 @@ br label %endif endif: - call void @nonconvergent_external(i8* %a_elt) + call void @noconvergent_external(i8* %a_elt) ret void } declare void @convergent_external(i8*) #0 -declare void @nonconvergent_external(i8*) #1 +declare void @noconvergent_external(i8*) #1 attributes #0 = { convergent nounwind } -attributes #1 = { nounwind } +attributes #1 = { noconvergent nounwind } Index: llvm/test/Transforms/CallSiteSplitting/musttail.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/musttail.ll +++ llvm/test/Transforms/CallSiteSplitting/musttail.ll @@ -24,7 +24,7 @@ ret i8* null } -define i8* @callee(i8* %a, i8* %b) noinline { +define i8* @callee(i8* %a, i8* %b) noconvergent noinline { ret i8* %a } @@ -70,7 +70,7 @@ ret void } -define void @void_callee(i8* %a, i8* %b) noinline { +define void @void_callee(i8* %a, i8* %b) noconvergent noinline { ret void } Index: llvm/test/Transforms/CallSiteSplitting/noduplicate.ll =================================================================== --- llvm/test/Transforms/CallSiteSplitting/noduplicate.ll +++ llvm/test/Transforms/CallSiteSplitting/noduplicate.ll @@ -86,6 +86,6 @@ declare void @noduplicate_external(i8*) #0 declare void @nonnoduplicate_external(i8*) #1 -attributes #0 = { noduplicate nounwind } -attributes #1 = { nounwind } +attributes #0 = { noconvergent noduplicate nounwind } +attributes #1 = { noconvergent nounwind } Index: llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll =================================================================== --- llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll +++ llvm/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll @@ -39,7 +39,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { nounwind ssp } -; CHECK: attributes #1 = { nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { noconvergent nounwind readnone speculatable willreturn } ; CHECK: attributes #2 = { noinline nounwind ssp } ; CHECK: attributes [[NUW]] = { nounwind } Index: llvm/test/Transforms/ForcedFunctionAttrs/noconvergent.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/ForcedFunctionAttrs/noconvergent.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -S -forceattrs | FileCheck %s --check-prefix=CHECK-CONTROL +; RUN: opt < %s -S -forceattrs -force-attribute foo:noconvergent | FileCheck %s --check-prefix=CHECK-FOO +; RUN: opt < %s -S -passes=forceattrs -force-attribute foo:noconvergent | FileCheck %s --check-prefix=CHECK-FOO + +; CHECK-CONTROL: define void @foo() { +; CHECK-FOO: define void @foo() #0 { +define void @foo() { + ret void +} + +; CHECK-FOO: attributes #0 = { noconvergent } Index: llvm/test/Transforms/FunctionAttrs/arg_returned.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/arg_returned.ll +++ llvm/test/Transforms/FunctionAttrs/arg_returned.ll @@ -8,13 +8,13 @@ ; TEST SCC test returning an integer value argument ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define i32 @sink_r0(i32 returned %r) -; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; BOTH-NEXT: define i32 @scc_r1(i32 %a, i32 returned %r, i32 %b) -; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; BOTH-NEXT: define i32 @scc_r2(i32 %a, i32 %b, i32 returned %r) -; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; BOTH-NEXT: define i32 @scc_rX(i32 %a, i32 %b, i32 %r) ; ; FNATTR: define i32 @sink_r0(i32 returned %r) @@ -163,11 +163,11 @@ ; FNATTR: define double* @ptr_scc_r1(double* %a, double* readnone %r, double* nocapture readnone %b) ; FNATTR: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone %r) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @ptr_sink_r0(double* readnone returned "no-capture-maybe-returned" %r) -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @ptr_scc_r1(double* readnone %a, double* readnone returned %r, double* nocapture readnone %b) -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @ptr_scc_r2(double* readnone %a, double* readnone %b, double* readnone returned %r) ; ; double* ptr_scc_r1(double* a, double* b, double* r); @@ -253,7 +253,7 @@ ; } ; ; FNATTR: define i32* @rt0(i32* readonly %a) -; BOTH: Function Attrs: nofree noinline noreturn nosync nounwind readonly uwtable +; BOTH: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readonly uwtable ; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture nonnull readonly dereferenceable(4) %a) define i32* @rt0(i32* %a) #0 { entry: @@ -271,7 +271,7 @@ ; } ; ; FNATTR: define noalias i32* @rt1(i32* nocapture readonly %a) -; BOTH: Function Attrs: nofree noinline noreturn nosync nounwind readonly uwtable +; BOTH: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readonly uwtable ; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt1(i32* nocapture nonnull readonly dereferenceable(4) %a) define i32* @rt1(i32* %a) #0 { entry: @@ -432,11 +432,11 @@ ; return b == 0? b : x; ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double @select_and_phi(double returned %b) ; ; FNATTR: define double @select_and_phi(double %b) -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double @select_and_phi(double returned %b) define double @select_and_phi(double %b) #0 { entry: @@ -463,12 +463,12 @@ ; return b == 0? b : x; ; } ; -; BOTH: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; BOTH-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b) ; ; FNATTR: define double @recursion_select_and_phi(i32 %a, double %b) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double @recursion_select_and_phi(i32 %a, double returned %b) define double @recursion_select_and_phi(i32 %a, double %b) #0 { entry: @@ -494,12 +494,12 @@ ; return (double*)b; ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double* @bitcast(i32* readnone returned "no-capture-maybe-returned" %b) ; ; FNATTR: define double* @bitcast(i32* readnone %b) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @bitcast(i32* readnone returned "no-capture-maybe-returned" %b) define double* @bitcast(i32* %b) #0 { entry: @@ -517,12 +517,12 @@ ; return b != 0 ? b : x; ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double* @bitcasts_select_and_phi(i32* readnone returned %b) ; ; FNATTR: define double* @bitcasts_select_and_phi(i32* readnone %b) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @bitcasts_select_and_phi(i32* readnone returned %b) define double* @bitcasts_select_and_phi(i32* %b) #0 { entry: @@ -555,12 +555,12 @@ ; /* return undef */ ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double* @ret_arg_arg_undef(i32* readnone returned %b) ; ; FNATTR: define double* @ret_arg_arg_undef(i32* readnone %b) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @ret_arg_arg_undef(i32* readnone returned %b) define double* @ret_arg_arg_undef(i32* %b) #0 { entry: @@ -593,12 +593,12 @@ ; /* return undef */ ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double* @ret_undef_arg_arg(i32* readnone returned %b) ; ; FNATTR: define double* @ret_undef_arg_arg(i32* readnone %b) ; -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define double* @ret_undef_arg_arg(i32* readnone returned %b) define double* @ret_undef_arg_arg(i32* %b) #0 { entry: @@ -631,7 +631,7 @@ ; /* return undef */ ; } ; -; BOTH: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; BOTH: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; BOTH-NEXT: define double* @ret_undef_arg_undef(i32* readnone returned %b) ; ; FNATTR: define double* @ret_undef_arg_undef(i32* readnone %b) @@ -839,13 +839,13 @@ attributes #0 = { noinline nounwind uwtable } ; BOTH-NOT: attributes # -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline noreturn nosync nounwind readonly uwtable } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree noinline norecurse nosync nounwind readnone uwtable willreturn } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree noinline nosync nounwind readnone uwtable } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree noinline noreturn nosync nounwind readonly uwtable } ; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable } ; BOTH-DAG: attributes #{{[0-9]*}} = { noreturn } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree nosync readnone willreturn } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree nosync readnone } -; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noreturn nosync readonly } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree noinline norecurse nosync nounwind readnone uwtable } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree nosync readnone willreturn } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree nosync readnone } +; BOTH-DAG: attributes #{{[0-9]*}} = { noconvergent nofree noreturn nosync readonly } ; BOTH-NOT: attributes # Index: llvm/test/Transforms/FunctionAttrs/atomic.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/atomic.ll +++ llvm/test/Transforms/FunctionAttrs/atomic.ll @@ -20,5 +20,5 @@ ret i32 %r } -; CHECK: attributes #0 = { norecurse nounwind readnone ssp uwtable } -; CHECK: attributes #1 = { nofree norecurse nounwind ssp uwtable } +; CHECK: attributes #0 = { noconvergent norecurse nounwind readnone ssp uwtable } +; CHECK: attributes #1 = { noconvergent nofree norecurse nounwind ssp uwtable } Index: llvm/test/Transforms/FunctionAttrs/convergent.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/convergent.ll +++ /dev/null @@ -1,110 +0,0 @@ -; FIXME: convert CHECK-INDIRECT into CHECK (and remove -check-prefixes) as soon -; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed -; -; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT -; RUN: opt -passes=function-attrs -S < %s | FileCheck %s - -; CHECK: Function Attrs -; CHECK-NOT: convergent -; CHECK-NEXT: define i32 @nonleaf() -define i32 @nonleaf() convergent { - %a = call i32 @leaf() - ret i32 %a -} - -; CHECK: Function Attrs -; CHECK-NOT: convergent -; CHECK-NEXT: define i32 @leaf() -define i32 @leaf() convergent { - ret i32 0 -} - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: declare i32 @k() -declare i32 @k() convergent - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @extern() -define i32 @extern() convergent { - %a = call i32 @k() convergent - ret i32 %a -} - -; Convergent should not be removed on the function here. Although the call is -; not explicitly convergent, it picks up the convergent attr from the callee. -; -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @extern_non_convergent_call() -define i32 @extern_non_convergent_call() convergent { - %a = call i32 @k() - ret i32 %a -} - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @indirect_convergent_call( -define i32 @indirect_convergent_call(i32 ()* %f) convergent { - %a = call i32 %f() convergent - ret i32 %a -} -; Give indirect_non_convergent_call the norecurse attribute so we get a -; "Function Attrs" comment in the output. -; -; CHECK: Function Attrs -; CHECK-INDIRECT-NOT: convergent -; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call( -define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse { - %a = call i32 %f() - ret i32 %a -} - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: declare void @llvm.nvvm.barrier0() -declare void @llvm.nvvm.barrier0() convergent - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @intrinsic() -define i32 @intrinsic() convergent { - ; Implicitly convergent, because the intrinsic is convergent. - call void @llvm.nvvm.barrier0() - ret i32 0 -} - -; CHECK: Function Attrs -; CHECK-NOT: convergent -; CHECK-NEXT: define i32 @recursive1() -define i32 @recursive1() convergent { - %a = call i32 @recursive2() convergent - ret i32 %a -} - -; CHECK: Function Attrs -; CHECK-NOT: convergent -; CHECK-NEXT: define i32 @recursive2() -define i32 @recursive2() convergent { - %a = call i32 @recursive1() convergent - ret i32 %a -} - -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @noopt() -define i32 @noopt() convergent optnone noinline { - %a = call i32 @noopt_friend() convergent - ret i32 0 -} - -; A function which is mutually-recursive with a convergent, optnone function -; shouldn't have its convergent attribute stripped. -; CHECK: Function Attrs -; CHECK-SAME: convergent -; CHECK-NEXT: define i32 @noopt_friend() -define i32 @noopt_friend() convergent { - %a = call i32 @noopt() - ret i32 0 -} Index: llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll +++ llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll @@ -12,7 +12,7 @@ ; return srec0(); ; } ; -; CHECK: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; CHECK: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; CHECK: define void @srec0() ; define void @srec0() #0 { @@ -28,7 +28,7 @@ ; return srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(a)))))))))))))))); ; } ; -; CHECK: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; CHECK: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; CHECK: define i32 @srec16(i32 %a) ; define i32 @srec16(i32 %a) #0 { @@ -62,7 +62,7 @@ ; while (1); ; } ; -; CHECK: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable +; CHECK: Function Attrs: noconvergent nofree noinline norecurse noreturn nosync nounwind readnone uwtable ; CHECK: define i32 @endless_loop(i32 %a) ; define i32 @endless_loop(i32 %a) #0 { @@ -82,7 +82,7 @@ ; } ; ; FIXME: no-return missing (D65243 should fix this) -; CHECK: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable +; CHECK: Function Attrs: noconvergent nofree noinline norecurse noreturn nosync nounwind readnone uwtable ; CHECK: define i32 @dead_return(i32 returned %a) ; define i32 @dead_return(i32 %a) #0 { @@ -103,7 +103,7 @@ ; return a == 0 ? endless_loop(a) : srec16(a); ; } ; -; CHECK: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; CHECK: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; CHECK: define i32 @multiple_noreturn_calls(i32 %a) ; define i32 @multiple_noreturn_calls(i32 %a) #0 { @@ -126,7 +126,7 @@ ; TEST 6: willreturn means *not* no-return -; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; CHECK: Function Attrs: noconvergent nofree norecurse nosync nounwind readnone willreturn ; CHECK-NEXT: define i32 @endless_loop_but_willreturn define i32 @endless_loop_but_willreturn(i32 %a) willreturn { entry: Index: llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll +++ llvm/test/Transforms/FunctionAttrs/incompatible_fn_attrs.ll @@ -28,5 +28,5 @@ attributes #0 = { argmemonly } attributes #1 = { inaccessiblememonly } attributes #2 = { inaccessiblemem_or_argmemonly } -; CHECK: attributes #0 = { norecurse nounwind readnone } +; CHECK: attributes #0 = { noconvergent norecurse nounwind readnone } ; CHECK-NOT: attributes Index: llvm/test/Transforms/FunctionAttrs/liveness.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/liveness.ll +++ llvm/test/Transforms/FunctionAttrs/liveness.ll @@ -1,16 +1,16 @@ ; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s -declare void @no_return_call() nofree noreturn nounwind readnone +declare void @no_return_call() nofree noreturn nounwind readnone noconvergent -declare void @normal_call() readnone +declare void @normal_call() readnone noconvergent -declare i32 @foo() +declare i32 @foo() noconvergent -declare i32 @foo_noreturn_nounwind() noreturn nounwind +declare i32 @foo_noreturn_nounwind() noreturn nounwind noconvergent -declare i32 @foo_noreturn() noreturn +declare i32 @foo_noreturn() noreturn noconvergent -declare i32 @bar() nosync readnone +declare i32 @bar() nosync readnone noconvergent ; This internal function has no live call sites, so all its BBs are considered dead, ; and nothing should be deduced for it. @@ -33,13 +33,13 @@ br i1 %10, label %3, label %5 } -; CHECK: Function Attrs: nofree norecurse nounwind uwtable willreturn +; CHECK: Function Attrs: noconvergent nofree norecurse nounwind uwtable willreturn define i32 @volatile_load(i32*) norecurse nounwind uwtable { %2 = load volatile i32, i32* %0, align 4 ret i32 %2 } -; CHECK: Function Attrs: nofree norecurse nosync nounwind readonly uwtable willreturn +; CHECK: Function Attrs: noconvergent nofree norecurse nosync nounwind readonly uwtable willreturn ; CHECK-NEXT: define internal i32 @internal_load(i32* nocapture nonnull readonly dereferenceable(4) %0) define internal i32 @internal_load(i32*) norecurse nounwind uwtable { %2 = load i32, i32* %0, align 4 @@ -47,7 +47,7 @@ } ; TEST 1: Only first block is live. -; CHECK: Function Attrs: nofree noreturn nosync nounwind +; CHECK: Function Attrs: noconvergent nofree noreturn nosync nounwind ; CHECK-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nonnull readonly %ptr1, i32* nocapture readnone %ptr2) define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 { entry: @@ -83,7 +83,7 @@ ; This is just an example. For example we can put a sync call in a ; dead block and check if it is deduced. -; CHECK: Function Attrs: nosync +; CHECK: Function Attrs: noconvergent nosync ; CHECK-NEXT: define i32 @dead_block_present(i32 %a, i32* nocapture readnone %ptr1) define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 { entry: @@ -660,7 +660,7 @@ ; CHECK: define internal void @non_dead_d13() ; CHECK: define internal void @non_dead_d14() ; Verify we actually deduce information for these functions. -; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: noconvergent nofree nosync nounwind readnone willreturn ; CHECK-NEXT: define internal void @non_dead_d15() ; CHECK-NOT: define internal void @dead_e Index: llvm/test/Transforms/FunctionAttrs/noconvergent.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/FunctionAttrs/noconvergent.ll @@ -0,0 +1,118 @@ +; FIXME: convert CHECK-OLDPM into CHECK (and remove -check-prefixes) as soon +; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed +; RUN: opt -S -functionattrs %s | FileCheck -check-prefixes=CHECK,CHECK-OLDPM %s +; RUN: opt -S -passes=function-attrs %s | FileCheck -check-prefixes=CHECK,CHECK-NEWPM %s +; RUN: opt -S -attributor -attributor-disable=false -attributor-max-iterations=1 %s | FileCheck -check-prefixes=CHECK,CHECK-OLDPM %s +; RUN: opt -S -passes=attributor -attributor-disable=false -attributor-max-iterations=1 %s | FileCheck -check-prefixes=CHECK,CHECK-NEWPM %s + +; CHECK: Function Attrs +; CHECK: noconvergent +; CHECK-NEXT: define i32 @nonleaf() +define i32 @nonleaf() { + %a = call i32 @leaf() + ret i32 %a +} + +; CHECK: Function Attrs +; CHECK-SAME: noconvergent +; CHECK-NEXT: define i32 @leaf() +define i32 @leaf() { + ret i32 0 +} + +; CHECK: Function Attrs: noconvergent{{$}} +; CHECK-NEXT: declare i32 @extern_noconvergent() +declare i32 @extern_noconvergent() noconvergent + +; CHECK-NOT: Function Attrs +; CHECK: declare i32 @extern_convergent(){{$}} +declare i32 @extern_convergent() + +; CHECK-NOT: Function Attrs {{.*}}noconvergent{{.*}} +; CHECK: define i32 @call_extern_convergent() +define i32 @call_extern_convergent() { + %a = call i32 @extern_convergent() + ret i32 %a +} +; +; CHECK: Function Attrs +; CHECK-SAME: convergent +; CHECK-NEXT: define i32 @extern_noconvergent_call() +define i32 @extern_noconvergent_call() { + %a = call i32 @extern_noconvergent() + ret i32 %a +} + +; FIXME: This should work +; CHECK-NEWPM-NOT: Function Attrs {{.*}}noconvergent{{.*}} + +; CHECK-OLDPM: Function Attrs +; CHECK-OLDPM-SAME: noconvergent +; CHECK-OLDPM-NEXT: define i32 @indirect_noconvergent_call( +define i32 @indirect_noconvergent_call(i32 ()* %f) { + %a = call i32 %f() noconvergent + ret i32 %a +} +; Give indirect_non_convergent_call the norecurse attribute so we get a +; "Function Attrs" comment in the output. +; +; CHECK-OLDPM-NOT: Function Attrs {{.*}}noconvergent{{.*}} +; CHECK-OLDPM: define i32 @indirect_non_convergent_call( +define i32 @indirect_non_convergent_call(i32 ()* %f) norecurse { + %a = call i32 %f() + ret i32 %a +} + +; CHECK-NOT: Function Attrs {{.*}}noconvergent{{.*}} +; CHECK: declare void @llvm.nvvm.barrier0() +declare void @llvm.nvvm.barrier0() + +; CHECK: Function Attrs +; CHECK-NOT: noconvergent +; CHECK-NEXT: define i32 @intrinsic() +define i32 @intrinsic() { + ; Implicitly convergent, because the intrinsic is convergent. + call void @llvm.nvvm.barrier0() + ret i32 0 +} + +; CHECK: Function Attrs +; CHECK-SAME: noconvergent +; CHECK-NEXT: define i32 @convergent_intrinsic_noconvergent_callsite() +define i32 @convergent_intrinsic_noconvergent_callsite() { + call void @llvm.nvvm.barrier0() noconvergent + ret i32 0 +} + +; CHECK: Function Attrs +; CHECK: noconvergent +; CHECK-NEXT: define i32 @recursive1() +define i32 @recursive1() { + %a = call i32 @recursive2() + ret i32 %a +} + +; CHECK: Function Attrs +; CHECK: noconvergent +; CHECK-NEXT: define i32 @recursive2() +define i32 @recursive2() { + %a = call i32 @recursive1() + ret i32 %a +} + +; CHECK: Function Attrs +; CHECK-NOT: noconvergent +; CHECK-NEXT: define i32 @noopt() +define i32 @noopt() optnone noinline { + %a = call i32 @noopt_friend() + ret i32 0 +} + +; A function which is mutually-recursive with a convergent, optnone function +; shouldn't have noconvergent attribute added. +; CHECK-NOT: Function Attrs +; CHECK: define i32 @noopt_friend() +define i32 @noopt_friend() { + %a = call i32 @noopt() + ret i32 0 +} Index: llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll +++ llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll @@ -13,9 +13,9 @@ ; TEST 1 (positive case) -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readnone uwtable ; FNATTR-NEXT: define void @only_return() -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @only_return() define void @only_return() #0 { ret void @@ -90,18 +90,18 @@ ; } -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NEXT: define void @mutual_recursion1() -; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @mutual_recursion1() define void @mutual_recursion1() #0 { call void @mutual_recursion2() ret void } -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NEXT: define void @mutual_recursion2() -; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @mutual_recursion2() define void @mutual_recursion2() #0 { call void @mutual_recursion1() @@ -150,15 +150,15 @@ ; Call function declaration with "nofree" -; FNATTR: Function Attrs: nofree noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent nofree noinline nounwind readnone uwtable ; FNATTR-NEXT: declare void @nofree_function() -; ATTRIBUTOR: Function Attrs: nofree noinline nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nounwind readnone uwtable ; ATTRIBUTOR-NEXT: declare void @nofree_function() -declare void @nofree_function() nofree readnone #0 +declare void @nofree_function() nofree noconvergent readnone #0 -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NEXT: define void @call_nofree_function() -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @call_nofree_function() define void @call_nofree_function() #0 { tail call void @nofree_function() @@ -204,14 +204,14 @@ ; Call intrinsic function ; FNATTRS: Function Attrs: noinline readnone speculatable ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0) -; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable +; ATTRIBUTOR: Function Attrs: noconvergent nounwind readnone speculatable ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float) declare float @llvm.floor.f32(float) ; FNATTRS: Function Attrs: noinline nounwind uwtable ; FNATTRS-NEXT: define void @call_floor(float %a) ; FIXME: missing nofree -; ATTRIBUTOR: Function Attrs: noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @call_floor(float %a) define void @call_floor(float %a) #0 { @@ -224,7 +224,7 @@ ; FNATTRS: Function Attrs: noinline nounwind uwtable ; FNATTRS-NEXT: define void @f1() -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @f1() define void @f1() #0 { tail call void @nofree_function() @@ -233,7 +233,7 @@ ; FNATTRS: Function Attrs: noinline nounwind uwtable ; FNATTRS-NEXT: define void @f2() -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @f2() define void @f2() #0 { tail call void @f1() Index: llvm/test/Transforms/FunctionAttrs/nofree.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nofree.ll +++ llvm/test/Transforms/FunctionAttrs/nofree.ll @@ -107,7 +107,7 @@ ; CHECK: attributes #0 = { uwtable } ; CHECK: attributes #1 = { nounwind uwtable } ; CHECK: attributes #2 = { nounwind } -; CHECK: attributes #3 = { norecurse nounwind readonly uwtable } +; CHECK: attributes #3 = { noconvergent norecurse nounwind readonly uwtable } ; CHECK: attributes #4 = { nobuiltin nounwind } ; CHECK: attributes #5 = { builtin nounwind } Index: llvm/test/Transforms/FunctionAttrs/norecurse.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/norecurse.ll +++ llvm/test/Transforms/FunctionAttrs/norecurse.ll @@ -4,7 +4,7 @@ ; CHECK: Function Attrs ; CHECK-SAME: norecurse nounwind readnone -; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nosync nounwind readnone willreturn ; BOTH-NEXT: define i32 @leaf() define i32 @leaf() { ret i32 1 @@ -47,7 +47,7 @@ ; BOTH: Function Attrs ; BOTH-NEXT: declare i32 @k() -declare i32 @k() readnone +declare i32 @k() noconvergent readnone ; BOTH: Function Attrs ; CHECK-SAME: nounwind @@ -97,7 +97,7 @@ ret void } -; ATTRIBUTOR: Function Attrs: nofree nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nofree nosync nounwind ; ATTRIBUTOR-NEXT: define void @f(i32 %x) define void @f(i32 %x) { entry: @@ -145,7 +145,7 @@ declare void @unknown() ; Call an unknown function in a dead block. -; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nosync nounwind readnone willreturn ; ATTRIBUTOR: define i32 @call_unknown_in_dead_block() define i32 @call_unknown_in_dead_block() local_unnamed_addr { ret i32 0 Index: llvm/test/Transforms/FunctionAttrs/noreturn_async.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/noreturn_async.ll +++ llvm/test/Transforms/FunctionAttrs/noreturn_async.ll @@ -22,7 +22,7 @@ define dso_local void @"?overflow@@YAXXZ"() { entry: -; CHECK: Function Attrs: nofree noreturn nosync nounwind +; CHECK: Function Attrs: noconvergent nofree noreturn nosync nounwind ; CHECK-NEXT: define ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @"?overflow@@YAXXZ"() @@ -100,9 +100,9 @@ entry: %retval = alloca i32, align 4 %__exception_code = alloca i32, align 4 -; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() +; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() ; CHECK: to label %invoke.cont unwind label %catch.dispatch - invoke void @"?overflow@@YAXXZ_may_throw"() + invoke void @"?overflow@@YAXXZ_may_throw"() to label %invoke.cont unwind label %catch.dispatch invoke.cont: ; preds = %entry Index: llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll +++ llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll @@ -22,7 +22,7 @@ define dso_local void @"?overflow@@YAXXZ"() { entry: -; CHECK: Function Attrs: nofree noreturn nosync nounwind +; CHECK: Function Attrs: noconvergent nofree noreturn nosync nounwind ; CHECK-NEXT: define ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @"?overflow@@YAXXZ"() @@ -33,13 +33,13 @@ } -; CHECK: Function Attrs: nofree noreturn nosync nounwind +; CHECK: Function Attrs: noconvergent nofree noreturn nosync nounwind ; CHECK-NEXT: @"?catchoverflow@@YAHXZ"() define dso_local i32 @"?catchoverflow@@YAHXZ"() personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) { entry: %retval = alloca i32, align 4 %__exception_code = alloca i32, align 4 - invoke void @"?overflow@@YAXXZ"() + invoke void @"?overflow@@YAXXZ"() to label %invoke.cont unwind label %catch.dispatch ; CHECK: call void @"?overflow@@YAXXZ"() ; CHECK-NEXT: unreachable @@ -96,9 +96,9 @@ entry: %retval = alloca i32, align 4 %__exception_code = alloca i32, align 4 -; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() +; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() ; CHECK: to label %invoke.cont unwind label %catch.dispatch - invoke void @"?overflow@@YAXXZ_may_throw"() + invoke void @"?overflow@@YAXXZ_may_throw"() to label %invoke.cont unwind label %catch.dispatch invoke.cont: ; preds = %entry Index: llvm/test/Transforms/FunctionAttrs/nosync.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nosync.ll +++ llvm/test/Transforms/FunctionAttrs/nosync.ll @@ -25,9 +25,9 @@ %struct.RT = type { i8, [10 x [20 x i32]], i8 } %struct.ST = type { i32, double, %struct.RT } -; FNATTR: Function Attrs: norecurse nounwind optsize readnone ssp uwtable +; FNATTR: Function Attrs: noconvergent norecurse nounwind optsize readnone ssp uwtable ; FNATTR-NEXT: define nonnull i32* @foo(%struct.ST* readnone %s) -; ATTRIBUTOR: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree nosync nounwind optsize readnone ssp uwtable ; ATTRIBUTOR-NEXT: define nonnull i32* @foo(%struct.ST* readnone "no-capture-maybe-returned" %s) define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp { entry: @@ -42,9 +42,9 @@ ; return n; ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define i32 @load_monotonic(i32* nocapture readonly %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nosync nounwind uwtable ; ATTRIBUTOR-NEXT: define i32 @load_monotonic(i32* nocapture nonnull readonly dereferenceable(4) %0) define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable { %2 = load atomic i32, i32* %0 monotonic, align 4 @@ -58,10 +58,10 @@ ; atomic_load_explicit(num, memory_order_relaxed); ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define void @store_monotonic(i32* nocapture %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nosync nounwind uwtable -; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture nonnull writeonly dereferenceable(4) %0) +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nosync nounwind uwtable +; ATTRIBUTOR-NEXT: define void @store_monotonic(i32* nocapture nonnull writeonly dereferenceable(4) %0) define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable { store atomic i32 10, i32* %0 monotonic, align 4 ret void @@ -74,9 +74,9 @@ ; return n; ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define i32 @load_acquire(i32* nocapture readonly %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define i32 @load_acquire(i32* nocapture nonnull readonly dereferenceable(4) %0) define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable { @@ -90,9 +90,9 @@ ; atomic_store_explicit(num, 10, memory_order_release); ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define void @load_release(i32* nocapture %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define void @load_release(i32* nocapture writeonly %0) define void @load_release(i32* nocapture %0) norecurse nounwind uwtable { @@ -102,9 +102,9 @@ ; TEST 6 - negative volatile, relaxed atomic -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define void @load_volatile_release(i32* nocapture %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define void @load_volatile_release(i32* nocapture writeonly %0) define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable { @@ -118,9 +118,9 @@ ; *num = 14; ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define void @volatile_store(i32* %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define void @volatile_store(i32* %0) define void @volatile_store(i32* %0) norecurse nounwind uwtable { @@ -135,9 +135,9 @@ ; return n; ; } -; FNATTR: Function Attrs: nofree norecurse nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; FNATTR-NEXT: define i32 @volatile_load(i32* %0) -; ATTRIBUTOR: Function Attrs: nofree norecurse nounwind uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree norecurse nounwind uwtable ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define i32 @volatile_load(i32* %0) define i32 @volatile_load(i32* %0) norecurse nounwind uwtable { @@ -183,9 +183,9 @@ ; TEST 11 - positive, should deduce nosync ; volatile operation in same scc but dead. Call volatile_load defined in TEST 8. -; FNATTR: Function Attrs: nofree noinline nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree noinline nounwind uwtable ; FNATTR-NEXT: define i32 @scc1(i32* %0) -; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define i32 @scc1(i32* nocapture readnone %0) define i32 @scc1(i32* %0) noinline nounwind uwtable { tail call void @scc2(i32* %0); @@ -193,9 +193,9 @@ ret i32 %val; } -; FNATTR: Function Attrs: nofree noinline nounwind uwtable +; FNATTR: Function Attrs: noconvergent nofree noinline nounwind uwtable ; FNATTR-NEXT: define void @scc2(i32* %0) -; ATTRIBUTOR: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline noreturn nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @scc2(i32* nocapture readnone %0) define void @scc2(i32* %0) noinline nounwind uwtable { tail call i32 @scc1(i32* %0); @@ -221,7 +221,7 @@ %"struct.std::atomic" = type { %"struct.std::__atomic_base" } %"struct.std::__atomic_base" = type { i8 } -; FNATTR: Function Attrs: nofree norecurse nounwind +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind ; FNATTR-NEXT: define void @foo1(i32* nocapture %0, %"struct.std::atomic"* nocapture %1) ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR: define void @foo1(i32* nocapture nonnull writeonly dereferenceable(4) %0, %"struct.std::atomic"* nocapture writeonly %1) @@ -234,7 +234,7 @@ ret void } -; FNATTR: Function Attrs: nofree norecurse nounwind +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind ; FNATTR-NEXT: define void @bar(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1) ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR: define void @bar(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1) @@ -254,9 +254,9 @@ } ; TEST 13 - Fence syncscope("singlethread") seq_cst -; FNATTR: Function Attrs: nofree norecurse nounwind +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind ; FNATTR-NEXT: define void @foo1_singlethread(i32* nocapture %0, %"struct.std::atomic"* nocapture %1) -; ATTRIBUTOR: Function Attrs: nofree nosync nounwind willreturn +; ATTRIBUTOR: Function Attrs: noconvergent nofree nosync nounwind willreturn ; ATTRIBUTOR: define void @foo1_singlethread(i32* nocapture nonnull writeonly dereferenceable(4) %0, %"struct.std::atomic"* nocapture writeonly %1) define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) { @@ -267,9 +267,9 @@ ret void } -; FNATTR: Function Attrs: nofree norecurse nounwind +; FNATTR: Function Attrs: noconvergent nofree norecurse nounwind ; FNATTR-NEXT: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1) -; ATTRIBUTOR: Function Attrs: nofree nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nofree nosync nounwind ; ATTRIBUTOR: define void @bar_singlethread(i32* nocapture readnone %0, %"struct.std::atomic"* nocapture readonly %1) define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) { %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 @@ -293,7 +293,7 @@ ; It is odd to add nocapture but a result of the llvm.memcpy nocapture. ; -; ATTRIBUTOR: Function Attrs: nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nounwind ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define i32 @memcpy_volatile(i8* nocapture writeonly %ptr1, i8* nocapture readonly %ptr2) define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) { @@ -305,7 +305,7 @@ ; It is odd to add nocapture but a result of the llvm.memset nocapture. ; -; ATTRIBUTOR: Function Attrs: nosync +; ATTRIBUTOR: Function Attrs: noconvergent nosync ; ATTRIBUTOR-NEXT: define i32 @memset_non_volatile(i8* nocapture writeonly %ptr1, i8 %val) define i32 @memset_non_volatile(i8* %ptr1, i8 %val) { call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0) @@ -320,23 +320,24 @@ ret i32 4 } -declare void @readnone_test() convergent readnone +; convergent +declare void @readnone_test() readnone ; ATTRIBUTOR: define void @convergent_readnone() ; TEST 17 - negative. Convergent -define void @convergent_readnone(){ +define void @convergent_readnone() { call void @readnone_test() ret void } -; ATTRIBUTOR: Function Attrs: nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nounwind ; ATTRIBUTOR-NEXT: declare void @llvm.x86.sse2.clflush(i8*) declare void @llvm.x86.sse2.clflush(i8*) @a = common global i32 0, align 4 ; TEST 18 - negative. Synchronizing intrinsic -; ATTRIBUTOR: Function Attrs: nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nounwind ; ATTRIBUTOR-NOT: nosync ; ATTRIBUTOR-NEXT: define void @i_totally_sync() define void @i_totally_sync() { @@ -344,11 +345,11 @@ ret void } -declare float @llvm.cos(float %val) readnone +declare float @llvm.cos(float %val) noconvergent readnone ; TEST 19 - positive, readnone & non-convergent intrinsic. -; ATTRIBUTOR: Function Attrs: nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nosync nounwind ; ATTRIBUTOR-NEXT: define i32 @cos_test(float %x) define i32 @cos_test(float %x) { call float @llvm.cos(float %x) Index: llvm/test/Transforms/FunctionAttrs/nounwind.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/nounwind.ll +++ llvm/test/Transforms/FunctionAttrs/nounwind.ll @@ -2,18 +2,18 @@ ; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S | FileCheck %s --check-prefix=ATTRIBUTOR ; TEST 1 -; CHECK: Function Attrs: norecurse nounwind readnone +; CHECK: Function Attrs: noconvergent norecurse nounwind readnone ; CHECK-NEXT: define i32 @foo1() -; ATTRIBUTOR: Function Attrs: nofree nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nofree nosync nounwind ; ATTRIBUTOR-NEXT: define i32 @foo1() define i32 @foo1() { ret i32 1 } ; TEST 2 -; CHECK: Function Attrs: nounwind readnone +; CHECK: Function Attrs: noconvergent nounwind readnone ; CHECK-NEXT: define i32 @scc1_foo() -; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nofree noreturn nosync nounwind ; ATTRIBUTOR-NEXT: define i32 @scc1_foo() define i32 @scc1_foo() { %1 = call i32 @scc1_bar() @@ -22,9 +22,9 @@ ; TEST 3 -; CHECK: Function Attrs: nounwind readnone +; CHECK: Function Attrs: noconvergent nounwind readnone ; CHECK-NEXT: define i32 @scc1_bar() -; ATTRIBUTOR: Function Attrs: nofree noreturn nosync nounwind +; ATTRIBUTOR: Function Attrs: noconvergent nofree noreturn nosync nounwind ; ATTRIBUTOR-NEXT: define i32 @scc1_bar() define i32 @scc1_bar() { %1 = call i32 @scc1_foo() Index: llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll +++ llvm/test/Transforms/FunctionAttrs/operand-bundles-scc.ll @@ -14,4 +14,4 @@ } -; CHECK: attributes #0 = { nofree nounwind } +; CHECK: attributes #0 = { noconvergent nofree nounwind } Index: llvm/test/Transforms/FunctionAttrs/optnone.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/optnone.ll +++ llvm/test/Transforms/FunctionAttrs/optnone.ll @@ -20,6 +20,6 @@ ; CHECK: (i8*) #1 ; CHECK-LABEL: attributes #0 -; CHECK: = { norecurse nounwind readnone } +; CHECK: = { noconvergent norecurse nounwind readnone } ; CHECK-LABEL: attributes #1 ; CHECK: = { noinline optnone } Index: llvm/test/Transforms/FunctionAttrs/read-write-scc.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/read-write-scc.ll +++ llvm/test/Transforms/FunctionAttrs/read-write-scc.ll @@ -17,4 +17,4 @@ ret void } -; CHECK: attributes #0 = { nofree nounwind } +; CHECK: attributes #0 = { noconvergent nofree nounwind } Index: llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll +++ llvm/test/Transforms/FunctionAttrs/read_write_returned_arguments_scc.ll @@ -29,7 +29,7 @@ ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -; CHECK: Function Attrs: nofree nosync nounwind +; CHECK: Function Attrs: noconvergent nofree nosync nounwind ; CHECK-NEXT: define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* returned %w0) define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { entry: @@ -40,7 +40,7 @@ ret i32* %call3 } -; CHECK: Function Attrs: nofree nosync nounwind +; CHECK: Function Attrs: noconvergent nofree nosync nounwind ; CHECK-NEXT: define internal i32* @internal_ret0_nw(i32* returned %n0, i32* %w0) define internal i32* @internal_ret0_nw(i32* %n0, i32* %w0) { entry: @@ -69,7 +69,7 @@ ret i32* %retval.0 } -; CHECK: Function Attrs: nofree nosync nounwind +; CHECK: Function Attrs: noconvergent nofree nosync nounwind ; CHECK-NEXT: define internal i32* @internal_ret1_rrw(i32* nonnull dereferenceable(4) %r0, i32* returned %r1, i32* %w0) define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) { entry: @@ -101,7 +101,7 @@ ret i32* %retval.0 } -; CHECK: Function Attrs: nofree norecurse nosync nounwind +; CHECK: Function Attrs: noconvergent nofree norecurse nosync nounwind ; CHECK-NEXT: define i32* @external_sink_ret2_nrw(i32* readnone %n0, i32* nocapture readonly %r0, i32* returned writeonly "no-capture-maybe-returned" %w0) define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { entry: @@ -120,7 +120,7 @@ ret i32* %w0 } -; CHECK: Function Attrs: nofree nosync nounwind +; CHECK: Function Attrs: noconvergent nofree nosync nounwind ; CHECK-NEXT: define internal i32* @internal_ret1_rw(i32* nonnull dereferenceable(4) %r0, i32* returned %w0) define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0) { entry: @@ -146,7 +146,7 @@ ret i32* %retval.0 } -; CHECK: Function Attrs: nofree nosync nounwind +; CHECK: Function Attrs: noconvergent nofree nosync nounwind ; CHECK-NEXT: define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* returned %w0) define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { entry: @@ -159,7 +159,7 @@ ; for a subset relation. ; ; CHECK-NOT: attributes # -; CHECK: attributes #{{.*}} = { nofree nosync nounwind } -; CHECK: attributes #{{.*}} = { nofree norecurse nosync nounwind } +; CHECK: attributes #{{.*}} = { noconvergent nofree nosync nounwind } +; CHECK: attributes #{{.*}} = { noconvergent nofree norecurse nosync nounwind } ; CHECK: attributes #{{.*}} = { nosync } ; CHECK-NOT: attributes # Index: llvm/test/Transforms/FunctionAttrs/willreturn.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/willreturn.ll +++ llvm/test/Transforms/FunctionAttrs/willreturn.ll @@ -9,9 +9,9 @@ ; TEST 1 (positive case) -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readnone uwtable ; FNATTR-NEXT: define void @only_return() -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; ATTRIBUTOR-NEXT: define void @only_return() define void @only_return() #0 { ret void @@ -25,10 +25,10 @@ ; return n<=1? n : fib(n-1) + fib(n-2); ; } -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NEXT: define i32 @fib(i32 %0) ; FIXME: missing willreturn -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define i32 @fib(i32 %0) local_unnamed_addr define i32 @fib(i32 %0) local_unnamed_addr #0 { %2 = icmp slt i32 %0, 2 @@ -56,10 +56,10 @@ ; } ; fact_maybe_not(-1) doesn't stop. -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readnone uwtable ; FNATTR-NOT: willreturn ; FNATTR-NEXT: define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr #0 { @@ -93,9 +93,9 @@ ; } ; FIXME: missing willreturn -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readnone uwtable ; FNATTR-NEXT: define i32 @fact_loop(i32 %0) -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define i32 @fact_loop(i32 %0) local_unnamed_addr define i32 @fact_loop(i32 %0) local_unnamed_addr #0 { %2 = icmp slt i32 %0, 1 @@ -123,10 +123,10 @@ ; mutual_recursion1(); ; } -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NOT: willreturn ; FNATTR-NEXT: define void @mutual_recursion1(i1 %c) -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define void @mutual_recursion1(i1 %c) define void @mutual_recursion1(i1 %c) #0 { @@ -139,10 +139,10 @@ } -; FNATTR: Function Attrs: noinline nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind readnone uwtable ; FNATTR-NOT: willreturn ; FNATTR-NEXT: define void @mutual_recursion2(i1 %c) -; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define void @mutual_recursion2(i1 %c) define void @mutual_recursion2(i1 %c) #0 { @@ -212,14 +212,14 @@ ; FIXME: missing willreturn ; FNATTRS: Function Attrs: noinline readnone speculatable ; FNATTRS-NEXT: declare float @llvm.floor.f32(float %0) -; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable +; ATTRIBUTOR: Function Attrs: noconvergent nounwind readnone speculatable ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float) declare float @llvm.floor.f32(float) ; FNATTRS: Function Attrs: noinline nounwind readnone uwtable ; FNATTRS-NEXT: define void @call_floor(float %a) ; FIXME: missing willreturn -; ATTRIBUTOR: Function Attrs: noinline nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent noinline nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define void @call_floor(float %a) define void @call_floor(float %a) #0 { tail call float @llvm.floor.f32(float %a) @@ -335,9 +335,9 @@ ; } ; FIXME: missing willreturn -; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readonly uwtable ; FNATTR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly %0) -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readonly uwtable ; ATTRIBUTOR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly %0) define i32 @loop_constant_trip_count(i32* nocapture readonly %0) #0 { br label %3 @@ -367,10 +367,10 @@ ; } ; return ans; ; } -; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readonly uwtable ; FNATTR-NOT: willreturn ; FNATTR-NEXT: define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readonly uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr #0 { @@ -406,9 +406,9 @@ ; FIXME: missing willreturn -; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readonly uwtable ; FNATTR-NEXT: define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readonly uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readonly uwtable ; ATTRIBUTOR-NEXT: define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) local_unnamed_addr define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) local_unnamed_addr #0 { @@ -437,9 +437,9 @@ ; TEST 14 (positive case) ; multiple return -; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable +; FNATTR: Function Attrs: noconvergent noinline norecurse nounwind readnone uwtable ; FNATTR-NEXT: define i32 @multiple_return(i32 %a) -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; ATTRIBUTOR-NEXT: define i32 @multiple_return(i32 %a) define i32 @multiple_return(i32 %a) #0 { %b = icmp eq i32 %a, 0 @@ -471,7 +471,7 @@ ; FIXME: missing willreturn ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-NEXT: define i32 @unreachable_exit_positive2(i32 %0) -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse nosync nounwind readnone uwtable ; ATTRIBUTOR-NEXT: define i32 @unreachable_exit_positive2(i32 %0) define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 { %2 = icmp slt i32 %0, 1 @@ -515,7 +515,7 @@ ; FNATTR: Function Attrs: noinline nounwind uwtable ; FNATTR-NOT: willreturn ; FNATTR-NEXT: define void @unreachable_exit_negative2() -; ATTRIBUTOR: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable +; ATTRIBUTOR: Function Attrs: noconvergent nofree noinline norecurse noreturn nosync nounwind readnone uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative2() define void @unreachable_exit_negative2() #0 { @@ -531,16 +531,16 @@ unreachable } -; FNATTR: Function Attrs: noreturn nounwind +; FNATTR: Function Attrs: noconvergent noreturn nounwind ; FNATTR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*) -; ATTRIBUTOR: Function Attrs: noreturn nounwind +; ATTRIBUTOR: Function Attrs: noconvergent noreturn nounwind ; ATTRIBUTOR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*) declare void @llvm.eh.sjlj.longjmp(i8*) -; FNATTR: Function Attrs: noinline nounwind uwtable +; FNATTR: Function Attrs: noconvergent noinline nounwind uwtable ; FNATTR-NOT: willreturn -; FNATTR-NEXT: define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #3 { -; ATTRIBUTOR: Function Attrs: noinline noreturn nounwind uwtable +; FNATTR-NEXT: define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #11 { +; ATTRIBUTOR: Function Attrs: noconvergent noinline noreturn nounwind uwtable ; ATTRIBUTOR-NOT: willreturn ; ATTRIBUTOR-NEXT: define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #0 { Index: llvm/test/Transforms/GVNHoist/hoist-convergent.ll =================================================================== --- llvm/test/Transforms/GVNHoist/hoist-convergent.ll +++ llvm/test/Transforms/GVNHoist/hoist-convergent.ll @@ -30,41 +30,11 @@ ret float %add } -; The call site is convergent but the declaration is not. -; CHECK-LABEL: @no_convergent_call_hoisting( - -; CHECK: if.then: -; CHECK: call float @func( - -; CHECK: if.else: -; CHECK: call float @func( -define float @no_convergent_call_hoisting(float %d, float %min, float %max, float %a) { -entry: - %div = fdiv float 1.000000e+00, %d - %cmp = fcmp oge float %div, 0.000000e+00 - br i1 %cmp, label %if.then, label %if.else - -if.then: - %sub1 = fsub float %max, %a - %mul2 = call float @func(float %sub1, float %div) #0 - br label %if.end - -if.else: - %sub5 = fsub float %max, %a - %mul6 = call float @func(float %sub5, float %div) #0 - br label %if.end - -if.end: - %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ] - %add = fadd float %tmax.0, 10.0 - ret float %add -} - -; The call site is convergent but the declaration is not. -; CHECK-LABEL: @call_hoisting( -; CHECK: call float @func( -; CHECK-NOT: call float @func( -define float @call_hoisting(float %d, float %min, float %max, float %a) { +; The call site is noconvergent but the declaration is not. +; CHECK-LABEL: @noconvergent_callsite_hoisting( +; CHECK: call float @convergent_func( +; CHECK-NOT: call float @convergent_func( +define float @noconvergent_callsite_hoisting(float %d, float %min, float %max, float %a) { entry: %div = fdiv float 1.000000e+00, %d %cmp = fcmp oge float %div, 0.000000e+00 @@ -72,12 +42,12 @@ if.then: %sub1 = fsub float %max, %a - %mul2 = call float @func(float %sub1, float %div) + %mul2 = call float @convergent_func(float %sub1, float %div) noconvergent br label %if.end if.else: %sub5 = fsub float %max, %a - %mul6 = call float @func(float %sub5, float %div) + %mul6 = call float @convergent_func(float %sub5, float %div) noconvergent br label %if.end if.end: @@ -87,7 +57,5 @@ } declare float @convergent_func(float, float) #0 -declare float @func(float, float) #1 -attributes #0 = { nounwind readnone convergent } -attributes #1 = { nounwind readnone } +attributes #0 = { nounwind readnone } Index: llvm/test/Transforms/GVNHoist/hoist-pr31891.ll =================================================================== --- llvm/test/Transforms/GVNHoist/hoist-pr31891.ll +++ llvm/test/Transforms/GVNHoist/hoist-pr31891.ll @@ -47,12 +47,12 @@ ; CHECK: ![[sp_hoistit]] = distinct !DISubprogram(name: "hoistit", {{.*}}) ; CHECK: ![[dbgloc]] = !DILocation({{.*}}, scope: ![[sp_hoistit]]) -declare void @useit1(float) +declare void @useit1(float) noconvergent -declare void @useit2(float) +declare void @useit2(float) noconvergent attributes #0 = { noinline nounwind readnone uwtable } -attributes #1 = { nounwind readnone } +attributes #1 = { noconvergent nounwind readnone } attributes #2 = { noinline nounwind uwtable } !llvm.dbg.cu = !{!0} Index: llvm/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll =================================================================== --- llvm/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll +++ llvm/test/Transforms/InferAddressSpaces/NVPTX/clone_constexpr.ll @@ -31,6 +31,6 @@ declare void @f2(i64*, i64) local_unnamed_addr #0 declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() #1 -attributes #0 = { convergent nounwind } -attributes #1 = { nounwind readnone } -attributes #2 = { nounwind } +attributes #0 = { nounwind } +attributes #1 = { noconvergent nounwind readnone } +attributes #2 = { noconvergent nounwind } Index: llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll =================================================================== --- llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll +++ llvm/test/Transforms/InferFunctionAttrs/norecurse_debug.ll @@ -52,5 +52,5 @@ !28 = !DILocation(line: 9, column: 18, scope: !2) !29 = !DILocation(line: 10, column: 1, scope: !2) -; CHECK: attributes #0 = { nofree norecurse nounwind } +; CHECK: attributes #0 = { noconvergent nofree norecurse nounwind } ; CHECK-NOT foo.coefficient1 Index: llvm/test/Transforms/Inline/cgscc-update.ll =================================================================== --- llvm/test/Transforms/Inline/cgscc-update.ll +++ llvm/test/Transforms/Inline/cgscc-update.ll @@ -152,7 +152,7 @@ ; form a new SCC and should use that can deduce precise function attrs. ; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: noinline nounwind readnone +; CHECK: Function Attrs: noconvergent noinline nounwind readnone ; CHECK-NEXT: define void @test4_f1() define void @test4_f1() noinline { entry: @@ -175,7 +175,7 @@ } ; This function should have had 'readnone' deduced for its SCC. -; CHECK: Function Attrs: noinline nounwind readnone +; CHECK: Function Attrs: noconvergent noinline nounwind readnone ; CHECK-NEXT: define void @test4_h() define void @test4_h() noinline { entry: Index: llvm/test/Transforms/Inline/inline_invoke.ll =================================================================== --- llvm/test/Transforms/Inline/inline_invoke.ll +++ llvm/test/Transforms/Inline/inline_invoke.ll @@ -343,7 +343,7 @@ ; CHECK-NEXT: call void @_ZSt9terminatev() ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nounwind readnone } +; CHECK: attributes #1 = { noconvergent nounwind readnone } ; CHECK: attributes #2 = { ssp uwtable } -; CHECK: attributes #3 = { argmemonly nounwind willreturn } +; CHECK: attributes #3 = { argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #4 = { noreturn nounwind } Index: llvm/test/Transforms/Inline/noalias-calls.ll =================================================================== --- llvm/test/Transforms/Inline/noalias-calls.ll +++ llvm/test/Transforms/Inline/noalias-calls.ll @@ -22,13 +22,13 @@ ret void } -; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 { +; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #3 { ; CHECK: entry: -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %b, i64 16, i1 false) #1, !noalias !0 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %b, i8* align 16 %c, i64 16, i1 false) #1, !noalias !3 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %c, i64 16, i1 false) #1, !alias.scope !5 -; CHECK: call void @hey() #1, !noalias !5 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %{{.*}}, i8* align 16 %c, i64 16, i1 false) #1, !noalias !3 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %b, i64 16, i1 false) #2, !noalias !0 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %b, i8* align 16 %c, i64 16, i1 false) #2, !noalias !3 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 %c, i64 16, i1 false) #2, !alias.scope !5 +; CHECK: call void @hey() #2, !noalias !5 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %{{.*}}, i8* align 16 %c, i64 16, i1 false) #2, !noalias !3 ; CHECK: ret void ; CHECK: } Index: llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll =================================================================== --- llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll +++ llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-intrinsics.ll @@ -1628,9 +1628,9 @@ ; llvm.amdgcn.icmp ; -------------------------------------------------------------------- -declare i64 @llvm.amdgcn.icmp.i64.i32(i32, i32, i32 immarg) nounwind readnone convergent -declare i64 @llvm.amdgcn.icmp.i64.i64(i64, i64, i32 immarg) nounwind readnone convergent -declare i64 @llvm.amdgcn.icmp.i64.i1(i1, i1, i32 immarg) nounwind readnone convergent +declare i64 @llvm.amdgcn.icmp.i64.i32(i32, i32, i32 immarg) nounwind readnone +declare i64 @llvm.amdgcn.icmp.i64.i64(i64, i64, i32 immarg) nounwind readnone +declare i64 @llvm.amdgcn.icmp.i64.i1(i1, i1, i32 immarg) nounwind readnone define i64 @invalid_icmp_code(i32 %a, i32 %b) { ; CHECK-LABEL: @invalid_icmp_code( @@ -1655,7 +1655,7 @@ define i64 @icmp_constant_inputs_true() { ; CHECK-LABEL: @icmp_constant_inputs_true( -; CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.read_register.i64(metadata !0) [[CONVERGENT:#[0-9]*]] +; CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.read_register.i64(metadata !0){{$}} ; CHECK-NEXT: ret i64 [[RESULT]] ; %result = call i64 @llvm.amdgcn.icmp.i64.i32(i32 9, i32 8, i32 34) @@ -2337,7 +2337,7 @@ ; llvm.amdgcn.fcmp ; -------------------------------------------------------------------- -declare i64 @llvm.amdgcn.fcmp.i64.f32(float, float, i32 immarg) nounwind readnone convergent +declare i64 @llvm.amdgcn.fcmp.i64.f32(float, float, i32 immarg) nounwind readnone define i64 @invalid_fcmp_code(float %a, float %b) { ; CHECK-LABEL: @invalid_fcmp_code( @@ -2362,7 +2362,7 @@ define i64 @fcmp_constant_inputs_true() { ; CHECK-LABEL: @fcmp_constant_inputs_true( -; CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.read_register.i64(metadata !0) [[CONVERGENT]] +; CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.read_register.i64(metadata !0){{$}} ; CHECK-NEXT: ret i64 [[RESULT]] ; %result = call i64 @llvm.amdgcn.fcmp.i64.f32(float 2.0, float 4.0, i32 4) @@ -2654,6 +2654,3 @@ store i32 %tmp0, i32 addrspace(1)* %out ret void } - -; CHECK: attributes [[CONVERGENT]] = { convergent } - Index: llvm/test/Transforms/InstCombine/convergent.ll =================================================================== --- llvm/test/Transforms/InstCombine/convergent.ll +++ /dev/null @@ -1,44 +0,0 @@ -; RUN: opt -instcombine -S < %s | FileCheck -enable-var-scope %s - -declare i32 @k() convergent -declare i32 @f() - -declare i64 @llvm.read_register.i64(metadata) nounwind - -define i32 @extern() { - ; Convergent attr shouldn't be removed here; k is convergent. - ; CHECK: call i32 @k() [[$CONVERGENT_ATTR:#[0-9]+]] - %a = call i32 @k() convergent - ret i32 %a -} - -define i32 @extern_no_attr() { - ; Convergent attr shouldn't be added here, even though k is convergent. - ; CHECK: call i32 @k(){{$}} - %a = call i32 @k() - ret i32 %a -} - -define i32 @no_extern() { - ; Convergent should be removed here, as the target is convergent. - ; CHECK: call i32 @f(){{$}} - %a = call i32 @f() convergent - ret i32 %a -} - -define i32 @indirect_call(i32 ()* %f) { - ; CHECK: call i32 %f() [[$CONVERGENT_ATTR]] - %a = call i32 %f() convergent - ret i32 %a -} - -; do not remove from convergent intrinsic call sites -; CHECK-LABEL: @convergent_intrinsic_call( -; CHECK: call i64 @llvm.read_register.i64(metadata !0) [[$CONVERGENT_ATTR]] -define i64 @convergent_intrinsic_call() { - %val = call i64 @llvm.read_register.i64(metadata !0) convergent - ret i64 %val -} - -; CHECK: [[$CONVERGENT_ATTR]] = { convergent } -!0 = !{!"foo"} Index: llvm/test/Transforms/InstCombine/sdiv-guard.ll =================================================================== --- llvm/test/Transforms/InstCombine/sdiv-guard.ll +++ llvm/test/Transforms/InstCombine/sdiv-guard.ll @@ -8,7 +8,7 @@ ; CHECK-LABEL: @a( ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[FLAG:%.*]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) #1 [ "deopt"() ] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) #2 [ "deopt"() ] ; CHECK-NEXT: [[R:%.*]] = sdiv i32 100, [[X]] ; CHECK-NEXT: ret i32 [[R]] ; Index: llvm/test/Transforms/JumpThreading/2010-08-26-and.ll =================================================================== --- llvm/test/Transforms/JumpThreading/2010-08-26-and.ll +++ llvm/test/Transforms/JumpThreading/2010-08-26-and.ll @@ -155,8 +155,8 @@ ret i32 0 } -declare i32 @printf(i8* nocapture, ...) nounwind +declare i32 @printf(i8* nocapture, ...) noconvergent nounwind -declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) nounwind readonly +declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) noconvergent nounwind readonly -declare i64 @strlen(i8* nocapture) nounwind readonly +declare i64 @strlen(i8* nocapture) noconvergent nounwind readonly Index: llvm/test/Transforms/JumpThreading/and-and-cond.ll =================================================================== --- llvm/test/Transforms/JumpThreading/and-and-cond.ll +++ llvm/test/Transforms/JumpThreading/and-and-cond.ll @@ -1,8 +1,8 @@ ; RUN: opt < %s -jump-threading -mem2reg -instcombine -simplifycfg -S | FileCheck %s -declare i32 @f1() -declare i32 @f2() -declare void @f3() +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent +declare void @f3() noconvergent define i32 @test(i1 %cond, i1 %cond2, i1 %cond3) { ; CHECK: test Index: llvm/test/Transforms/JumpThreading/and-cond.ll =================================================================== --- llvm/test/Transforms/JumpThreading/and-cond.ll +++ llvm/test/Transforms/JumpThreading/and-cond.ll @@ -1,8 +1,8 @@ ; RUN: opt < %s -jump-threading -mem2reg -instcombine -simplifycfg -S | FileCheck %s -declare i32 @f1() -declare i32 @f2() -declare void @f3() +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent +declare void @f3() noconvergent define i32 @test(i1 %cond, i1 %cond2) { ; CHECK: test Index: llvm/test/Transforms/JumpThreading/assume-edge-dom.ll =================================================================== --- llvm/test/Transforms/JumpThreading/assume-edge-dom.ll +++ llvm/test/Transforms/JumpThreading/assume-edge-dom.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -jump-threading < %s | FileCheck %s -declare i8* @escape() +declare i8* @escape() noconvergent declare void @llvm.assume(i1) define i1 @test1(i1 %cond) { Index: llvm/test/Transforms/JumpThreading/assume.ll =================================================================== --- llvm/test/Transforms/JumpThreading/assume.ll +++ llvm/test/Transforms/JumpThreading/assume.ll @@ -77,8 +77,8 @@ ret void } -declare void @f(i1) -declare void @exit() +declare void @f(i1) noconvergent +declare void @exit() noconvergent ; We can fold the assume but not the uses before the assume. define void @cannot_fold_use_before_assume(i32* %array) { ; CHECK-LABEL:@cannot_fold_use_before_assume @@ -100,7 +100,7 @@ ret void } -declare void @dummy(i1) nounwind argmemonly +declare void @dummy(i1) noconvergent nounwind argmemonly define void @can_fold_some_use_before_assume(i32* %array) { ; CHECK-LABEL:@can_fold_some_use_before_assume @@ -149,7 +149,7 @@ ret void } -declare void @fz(i8) +declare void @fz(i8) noconvergent ; FIXME: We can fold assume to true, and the use after assume, but we do not do so ; currently, because of the function call after the assume. define void @can_fold_assume2(i32* %array) { @@ -179,7 +179,7 @@ ret void } -declare void @llvm.experimental.guard(i1, ...) +declare void @llvm.experimental.guard(i1, ...) noconvergent ; FIXME: We can fold assume to true, but we do not do so ; because of the guard following the assume. define void @can_fold_assume3(i32* %array){ @@ -232,10 +232,10 @@ ; Function Attrs: nounwind declare void @llvm.assume(i1) #1 -declare void @bar(...) +declare void @bar(...) noconvergent -declare void @car(...) +declare void @car(...) noconvergent -attributes #0 = { nounwind uwtable } -attributes #1 = { nounwind } +attributes #0 = { noconvergent nounwind uwtable } +attributes #1 = { noconvergent nounwind } Index: llvm/test/Transforms/JumpThreading/basic.ll =================================================================== --- llvm/test/Transforms/JumpThreading/basic.ll +++ llvm/test/Transforms/JumpThreading/basic.ll @@ -1,8 +1,8 @@ ; RUN: opt -jump-threading -S < %s | FileCheck %s -declare i32 @f1() -declare i32 @f2() -declare void @f3() +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent +declare void @f3() noconvergent define i32 @test1(i1 %cond) { ; CHECK-LABEL: @test1( @@ -513,9 +513,9 @@ ; In this test we check that block duplication is inhibited by the presence ; of a function with the 'noduplicate' attribute. -declare void @g() -declare void @j() -declare void @k() +declare void @g() noconvergent +declare void @j() noconvergent +declare void @k() noconvergent ; CHECK-LABEL: define void @h(i32 %p) { define void @h(i32 %p) { @@ -589,9 +589,9 @@ br label %l3 l3: -; CHECK: call void @g() [[$CON:#[0-9]+]] +; CHECK: call void @g(){{$}} ; CHECK-NOT: call void @g() [[$CON]] - call void @g() convergent + call void @g() %y = icmp ult i32 %p, 5 br i1 %y, label %l4, label %l5 @@ -607,4 +607,3 @@ ; CHECK: attributes [[$NOD]] = { noduplicate } -; CHECK: attributes [[$CON]] = { convergent } Index: llvm/test/Transforms/JumpThreading/branch-no-const.ll =================================================================== --- llvm/test/Transforms/JumpThreading/branch-no-const.ll +++ llvm/test/Transforms/JumpThreading/branch-no-const.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -jump-threading -S | not grep phi -declare i8 @mcguffin() +declare i8 @mcguffin() noconvergent define i32 @test(i1 %foo, i8 %b) { entry: Index: llvm/test/Transforms/JumpThreading/callbr-edge-split.ll =================================================================== --- llvm/test/Transforms/JumpThreading/callbr-edge-split.ll +++ llvm/test/Transforms/JumpThreading/callbr-edge-split.ll @@ -55,4 +55,4 @@ ret i32 undef } -declare i32 @b() +declare i32 @b() noconvergent Index: llvm/test/Transforms/JumpThreading/combine-metadata.ll =================================================================== --- llvm/test/Transforms/JumpThreading/combine-metadata.ll +++ llvm/test/Transforms/JumpThreading/combine-metadata.ll @@ -3,7 +3,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" -declare void @use(i32 *) +declare void @use(i32 *) noconvergent ; Check that we propagate nonnull to dominated loads, when we find an available ; loaded value. Index: llvm/test/Transforms/JumpThreading/compare.ll =================================================================== --- llvm/test/Transforms/JumpThreading/compare.ll +++ llvm/test/Transforms/JumpThreading/compare.ll @@ -1,9 +1,9 @@ ; There should be no phi nodes left. ; RUN: opt < %s -jump-threading -S | not grep "phi i32" -declare i32 @f1() -declare i32 @f2() -declare void @f3() +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent +declare void @f3() noconvergent define i32 @test(i1 %cond) { br i1 %cond, label %T1, label %F1 Index: llvm/test/Transforms/JumpThreading/crash.ll =================================================================== --- llvm/test/Transforms/JumpThreading/crash.ll +++ llvm/test/Transforms/JumpThreading/crash.ll @@ -22,7 +22,7 @@ unreachable } -declare %struct.system__secondary_stack__mark_id @system__secondary_stack__ss_mark() +declare %struct.system__secondary_stack__mark_id @system__secondary_stack__ss_mark() noconvergent @@ -30,28 +30,28 @@ entry: br label %bb12 -bb6.us: - %tmp = icmp eq i32 undef, undef - %tmp1 = fsub double undef, undef - %tmp2 = fcmp ult double %tmp1, 0.000000e+00 +bb6.us: + %tmp = icmp eq i32 undef, undef + %tmp1 = fsub double undef, undef + %tmp2 = fcmp ult double %tmp1, 0.000000e+00 br i1 %tmp, label %bb6.us, label %bb13 -bb12: - %tmp3 = fcmp ult double undef, 0.000000e+00 +bb12: + %tmp3 = fcmp ult double undef, 0.000000e+00 br label %bb13 -bb13: +bb13: %.lcssa31 = phi double [ undef, %bb12 ], [ %tmp1, %bb6.us ] - %.lcssa30 = phi i1 [ %tmp3, %bb12 ], [ %tmp2, %bb6.us ] + %.lcssa30 = phi i1 [ %tmp3, %bb12 ], [ %tmp2, %bb6.us ] br i1 %.lcssa30, label %bb15, label %bb61 -bb15: - %tmp4 = fsub double -0.000000e+00, %.lcssa31 +bb15: + %tmp4 = fsub double -0.000000e+00, %.lcssa31 ret void -bb61: +bb61: ret void } @@ -63,14 +63,14 @@ F: br label %A1 -A1: +A1: %d = phi i1 [false, %A], [true, %F] %e = add i32 %a, %a br i1 %d, label %B, label %G - + G: br i1 %cond2, label %B, label %D - + B: %f = phi i32 [%e, %G], [%e, %A1] %b = add i32 0, 0 @@ -82,7 +82,7 @@ C: br label %D - + D: %c = phi i32 [%e, %B], [%e, %B], [%e, %B], [%f, %C], [%e, %G] ret i32 %c @@ -176,19 +176,19 @@ br i1 %tmp, label %bb12, label %bb13 -bb12: +bb12: br label %bb13 -bb13: +bb13: %.lcssa31 = phi i32 [ undef, %bb12 ], [ %tmp1, %entry ] %A = and i1 undef, undef br i1 %A, label %bb15, label %bb61 -bb15: +bb15: ret void -bb61: +bb61: ret void } @@ -198,18 +198,18 @@ entry: br i1 %tmp, label %bb12, label %bb14 -bb12: +bb12: br label %bb14 -bb14: +bb14: %A = phi i1 [ %A, %bb13 ], [ true, %bb12 ], [%tmp1, %entry] br label %bb13 -bb13: +bb13: br i1 %A, label %bb14, label %bb61 -bb61: +bb61: ret void } @@ -225,16 +225,16 @@ i32 3, label %bb ] -bb: +bb: switch i32 %x, label %return [ i32 2, label %bb2 i32 3, label %tailrecurse ] -bb2: +bb2: ret void -return: +return: ret void } @@ -324,7 +324,7 @@ br label %A A: ; preds = %entry - call void undef(i64 ptrtoint (i8* blockaddress(@test11, %A) to i64)) nounwind + call void undef(i64 ptrtoint (i8* blockaddress(@test11, %A) to i64)) noconvergent nounwind unreachable } @@ -350,7 +350,7 @@ define i32 @test13(i32* %P, i8* %Ptr) { entry: indirectbr i8* %Ptr, [label %BrBlock, label %B2] - + B2: store i32 4, i32 *%P br label %BrBlock @@ -359,7 +359,7 @@ %L = load i32, i32* %P %C = icmp eq i32 %L, 42 br i1 %C, label %T, label %F - + T: ret i32 123 F: @@ -394,7 +394,7 @@ define void @test15() nounwind { entry: ret void - + if.then237: br label %lbl_664 @@ -418,7 +418,7 @@ lbl_709: br label %if.end949 - + for.cond603: ; preds = %for.body607, %if.end336 br i1 undef, label %for.cond603, label %if.end949 @@ -448,16 +448,16 @@ lor.lhs.false.i: ; preds = %land.rhs br i1 %c3, label %land.end, label %land.end -land.end: +land.end: %0 = phi i1 [ true, %entry ], [ false, %land.rhs ], [false, %lor.lhs.false.i], [false, %lor.lhs.false.i] ; [#uses=1] - %cmp12 = and i1 %cmp, %0 + %cmp12 = and i1 %cmp, %0 %xor1 = xor i1 %cmp12, %c4 br i1 %xor1, label %if.then, label %if.end -if.then: +if.then: ret void -if.end: +if.end: ret void } @@ -561,9 +561,9 @@ unreachable } -declare i8* @PR14233.f1() +declare i8* @PR14233.f1() noconvergent -declare i8* @PR14233.f2() +declare i8* @PR14233.f2() noconvergent ; Make sure the following compiles in a sane amount of time, as opposed ; to taking exponential time. Index: llvm/test/Transforms/JumpThreading/ddt-crash.ll =================================================================== --- llvm/test/Transforms/JumpThreading/ddt-crash.ll +++ llvm/test/Transforms/JumpThreading/ddt-crash.ll @@ -8,7 +8,7 @@ @global = external global %struct.ham*, align 8 @global.1 = external constant i8* -declare i32 @wombat.2() +declare i32 @wombat.2() noconvergent define void @blam() { bb: @@ -165,7 +165,7 @@ ret void } -declare i32 @foo(...) +declare i32 @foo(...) noconvergent define void @zot() align 2 personality i8* bitcast (i32 (...)* @foo to i8*) { bb: @@ -262,4 +262,4 @@ unreachable } -declare void @bar() +declare void @bar() noconvergent Index: llvm/test/Transforms/JumpThreading/ddt-crash2.ll =================================================================== --- llvm/test/Transforms/JumpThreading/ddt-crash2.ll +++ llvm/test/Transforms/JumpThreading/ddt-crash2.ll @@ -37,4 +37,4 @@ ret void } -declare i32 @chrome2(...) +declare i32 @chrome2(...) noconvergent Index: llvm/test/Transforms/JumpThreading/fold-not-thread.ll =================================================================== --- llvm/test/Transforms/JumpThreading/fold-not-thread.ll +++ llvm/test/Transforms/JumpThreading/fold-not-thread.ll @@ -1,9 +1,9 @@ ; RUN: opt -jump-threading -S -verify < %s | FileCheck %s -declare i32 @f1() -declare i32 @f2() -declare void @f3() -declare void @f4(i32) +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent +declare void @f3() noconvergent +declare void @f4(i32) noconvergent ; Make sure we update the phi node properly. @@ -56,7 +56,7 @@ ; CHECK: L3: define void @test_br_folding_not_threading(i1 %cond) nounwind { entry: - br i1 %cond, label %L0, label %L3 + br i1 %cond, label %L0, label %L3 L0: call i32 @f2() call i32 @f2() @@ -71,7 +71,7 @@ call i32 @f2() call i32 @f2() call i32 @f2() - br i1 %cond, label %L1, label %L2 + br i1 %cond, label %L1, label %L2 L1: call void @f3() @@ -101,10 +101,10 @@ br i1 %condx, label %X0, label %X1 X0: - br i1 %cond, label %L0, label %L3 + br i1 %cond, label %L0, label %L3 X1: - br i1 %cond, label %L0, label %L3 + br i1 %cond, label %L0, label %L3 L0: call i32 @f2() @@ -120,7 +120,7 @@ call i32 @f2() call i32 @f2() call i32 @f2() - br i1 %cond, label %L1, label %L2 + br i1 %cond, label %L1, label %L2 L1: call void @f3() @@ -140,7 +140,7 @@ define void @rauw_if_possible(i32 %value) nounwind { entry: %cmp = icmp eq i32 %value, 32 - br i1 %cmp, label %L0, label %L3 + br i1 %cmp, label %L0, label %L3 L0: call i32 @f2() call i32 @f2() @@ -164,12 +164,12 @@ ; Make sure we can NOT do the RAUW for %add... ; ; CHECK-LABEL: @rauw_if_possible2( -; CHECK: call void @f4(i32 %add) +; CHECK: call void @f4(i32 %add) define void @rauw_if_possible2(i32 %value) nounwind { entry: %cmp = icmp eq i32 %value, 32 %add = add i32 %value, 64 - br i1 %cmp, label %L0, label %L2 + br i1 %cmp, label %L0, label %L2 L0: call i32 @f2() call i32 @f2() @@ -195,7 +195,7 @@ ; its target after L0 into account and that enables us to fold. ; ; L2 is the unreachable block here. -; +; ; CHECK-LABEL: @test_br_folding_not_threading_indirect_branch( ; CHECK: L1: ; CHECK: call i32 @f2() Index: llvm/test/Transforms/JumpThreading/guards.ll =================================================================== --- llvm/test/Transforms/JumpThreading/guards.ll +++ llvm/test/Transforms/JumpThreading/guards.ll @@ -1,9 +1,9 @@ ; RUN: opt < %s -jump-threading -dce -S | FileCheck %s -declare void @llvm.experimental.guard(i1, ...) +declare void @llvm.experimental.guard(i1, ...) noconvergent -declare i32 @f1() -declare i32 @f2() +declare i32 @f1() noconvergent +declare i32 @f2() noconvergent define i32 @branch_implies_guard(i32 %a) { ; CHECK-LABEL: @branch_implies_guard( @@ -182,7 +182,7 @@ ret void } -declare void @never_called(i1) +declare void @never_called(i1) noconvergent ; LVI uses guard to identify value of %c2 in branch as true, we cannot replace that ; guard with guard(true & c1). @@ -206,7 +206,7 @@ ret void } -declare void @dummy(i1) nounwind argmemonly +declare void @dummy(i1) noconvergent nounwind argmemonly ; same as dont_fold_guard1 but there's a use immediately after guard and before ; branch. We can fold that use. define void @dont_fold_guard2(i8* %addr, i32 %i, i32 %length) { @@ -248,19 +248,19 @@ ret void } -declare void @f(i1) +declare void @f(i1) noconvergent ; Same as dont_fold_guard1 but use switch instead of branch. ; triggers source code `ProcessThreadableEdges`. define void @dont_fold_guard4(i1 %cmp1, i32 %i) nounwind { -; CHECK-LABEL: dont_fold_guard4 +; CHECK-LABEL: dont_fold_guard4 ; CHECK-LABEL: L2: -; CHECK-NEXT: %cmp = icmp eq i32 %i, 0 +; CHECK-NEXT: %cmp = icmp eq i32 %i, 0 ; CHECK-NEXT: guard(i1 %cmp) ; CHECK-NEXT: dummy(i1 true) ; CHECK-NEXT: @f(i1 true) ; CHECK-NEXT: ret void entry: - br i1 %cmp1, label %L0, label %L3 + br i1 %cmp1, label %L0, label %L3 L0: %cmp = icmp eq i32 %i, 0 call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ] Index: llvm/test/Transforms/JumpThreading/header-succ.ll =================================================================== --- llvm/test/Transforms/JumpThreading/header-succ.ll +++ llvm/test/Transforms/JumpThreading/header-succ.ll @@ -4,7 +4,7 @@ ; loops doesn't also prevent us from threading simple constructs where this ; isn't a problem. -declare void @opaque_body() +declare void @opaque_body() noconvergent define void @jump_threading_loopheader() { ; CHECK-LABEL: @jump_threading_loopheader Index: llvm/test/Transforms/JumpThreading/implied-cond.ll =================================================================== --- llvm/test/Transforms/JumpThreading/implied-cond.ll +++ llvm/test/Transforms/JumpThreading/implied-cond.ll @@ -1,6 +1,6 @@ ; RUN: opt -jump-threading -S < %s | FileCheck %s -declare void @side_effect(i32) +declare void @side_effect(i32) noconvergent define void @test0(i32 %i, i32 %len) { ; CHECK-LABEL: @test0( @@ -126,7 +126,7 @@ ret void } -declare void @is(i1) +declare void @is(i1) noconvergent ; If A >=s B is false then A <=s B is implied true. ; CHECK-LABEL: @test_sge_sle Index: llvm/test/Transforms/JumpThreading/indirectbr.ll =================================================================== --- llvm/test/Transforms/JumpThreading/indirectbr.ll +++ llvm/test/Transforms/JumpThreading/indirectbr.ll @@ -6,8 +6,8 @@ i8* blockaddress(@test2, %L1), i8* blockaddress(@test2, %L2) ] -declare void @bar() -declare void @baz() +declare void @bar() noconvergent +declare void @baz() noconvergent @@ -91,4 +91,4 @@ ret void } -declare i32 @printf(...) noredzone +declare i32 @printf(...) noconvergent noredzone Index: llvm/test/Transforms/JumpThreading/landing-pad.ll =================================================================== --- llvm/test/Transforms/JumpThreading/landing-pad.ll +++ llvm/test/Transforms/JumpThreading/landing-pad.ll @@ -35,7 +35,7 @@ ret void } -declare void @_ZN24CompositeEditCommandImplC2Ev() #1 +declare void @_ZN24CompositeEditCommandImplC2Ev() noconvergent define void @_ZN1D7doApplyEv(%class.D* nocapture %this) unnamed_addr nounwind readnone uwtable align 2 { entry: @@ -107,11 +107,11 @@ ret void } -declare noalias i8* @_Znwm() +declare noalias i8* @_Znwm() noconvergent -declare i32 @__gxx_personality_v0(...) +declare i32 @__gxx_personality_v0(...) noconvergent -declare void @_ZdlPv() +declare void @_ZdlPv() noconvergent define %class.D* @_ZN1BI1DEptEv(%class.B* nocapture readonly %this) nounwind readonly uwtable align 2 { entry: @@ -120,7 +120,7 @@ ret %class.D* %0 } -declare void @_ZN1D16deleteKeyPressedEv() +declare void @_ZN1D16deleteKeyPressedEv() noconvergent define void @_ZN1BI1DED1Ev(%class.B* nocapture readonly %this) unnamed_addr uwtable align 2 { entry: @@ -142,7 +142,7 @@ ret void } -declare hidden void @__clang_call_terminate() +declare hidden void @__clang_call_terminate() noconvergent define void @_ZN1BI1DED2Ev(%class.B* nocapture readonly %this) unnamed_addr uwtable align 2 { entry: Index: llvm/test/Transforms/JumpThreading/lvi-load.ll =================================================================== --- llvm/test/Transforms/JumpThreading/lvi-load.ll +++ llvm/test/Transforms/JumpThreading/lvi-load.ll @@ -44,6 +44,6 @@ ret i8 0 } -declare void @__assert_rtn(i8*, i8*, i32, i8*) noreturn +declare void @__assert_rtn(i8*, i8*, i32, i8*) noconvergent noreturn -declare void @_ZNK4llvm5Value4dumpEv(%"struct.llvm::Value"*) +declare void @_ZNK4llvm5Value4dumpEv(%"struct.llvm::Value"*) noconvergent Index: llvm/test/Transforms/JumpThreading/lvi-tristate.ll =================================================================== --- llvm/test/Transforms/JumpThreading/lvi-tristate.ll +++ llvm/test/Transforms/JumpThreading/lvi-tristate.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -jump-threading -simplifycfg -S < %s | FileCheck %s -declare void @ham() +declare void @ham() noconvergent define void @hoge() { ; CHECK-LABEL: @hoge( Index: llvm/test/Transforms/JumpThreading/or-undef.ll =================================================================== --- llvm/test/Transforms/JumpThreading/or-undef.ll +++ llvm/test/Transforms/JumpThreading/or-undef.ll @@ -56,14 +56,14 @@ ret void } -declare noalias i8** @buildargv(i8*) +declare noalias i8** @buildargv(i8*) noconvergent -declare void @f2(i8**) +declare void @f2(i8**) noconvergent -declare void @f4(i8*) +declare void @f4(i8*) noconvergent -declare i8* @f3(void (i8*)*, i8*) +declare i8* @f3(void (i8*)*, i8*) noconvergent -declare void @f1() +declare void @f1() noconvergent -declare i64 @f5(i8*) +declare i64 @f5(i8*) noconvergent Index: llvm/test/Transforms/JumpThreading/phi-eq.ll =================================================================== --- llvm/test/Transforms/JumpThreading/phi-eq.ll +++ llvm/test/Transforms/JumpThreading/phi-eq.ll @@ -1,8 +1,8 @@ ; RUN: opt < %s -jump-threading -S | FileCheck %s ; Test whether two consecutive switches with identical structures assign the -; proper value to the proper variable. This is really testing -; Instruction::isIdenticalToWhenDefined, as previously that function was -; returning true if the value part of the operands of two phis were identical, +; proper value to the proper variable. This is really testing +; Instruction::isIdenticalToWhenDefined, as previously that function was +; returning true if the value part of the operands of two phis were identical, ; even if the incoming blocks were not. ; NB: this function should be pruned down more. @@ -19,13 +19,13 @@ @display_edited_filters = external hidden global %struct._GList*, align 8 @__PRETTY_FUNCTION__.get_filter_list = external hidden unnamed_addr constant [44 x i8], align 1 -declare void @g_assertion_message(i8*, i8*, i32, i8*, i8*) noreturn +declare void @g_assertion_message(i8*, i8*, i32, i8*, i8*) noconvergent noreturn -declare void @g_free(i8*) +declare void @g_free(i8*) noconvergent -declare %struct._GList* @g_list_first(%struct._GList*) +declare %struct._GList* @g_list_first(%struct._GList*) noconvergent -declare noalias i8* @g_malloc(i64) +declare noalias i8* @g_malloc(i64) noconvergent define void @copy_filter_list(i32 %dest_type, i32 %src_type) nounwind uwtable ssp { entry: @@ -198,12 +198,12 @@ ret void } -declare void @g_assertion_message_expr(i8*, i8*, i32, i8*, i8*) noreturn +declare void @g_assertion_message_expr(i8*, i8*, i32, i8*, i8*) noconvergent noreturn -declare i32 @g_list_length(%struct._GList*) +declare i32 @g_list_length(%struct._GList*) noconvergent -declare noalias i8* @g_strdup(i8*) +declare noalias i8* @g_strdup(i8*) noconvergent -declare %struct._GList* @g_list_append(%struct._GList*, i8*) +declare %struct._GList* @g_list_append(%struct._GList*, i8*) noconvergent -declare %struct._GList* @g_list_remove_link(%struct._GList*, %struct._GList*) +declare %struct._GList* @g_list_remove_link(%struct._GList*, %struct._GList*) noconvergent Index: llvm/test/Transforms/JumpThreading/phi-known.ll =================================================================== --- llvm/test/Transforms/JumpThreading/phi-known.ll +++ llvm/test/Transforms/JumpThreading/phi-known.ll @@ -34,7 +34,7 @@ ; CHECK-NEXT: bitcast ; CHECK-NEXT: load ; CHECK-NEXT: cmp -; CHECK-NEXT: br +; CHECK-NEXT: br ; CHECK-DAG: label %backedge %addr = bitcast i8* %p1 to i8** %p2 = load i8*, i8** %addr @@ -67,8 +67,8 @@ ; The eq predicate is always true if we go through the path from ; L1 to L3, no matter the phi result %t5 is on the lhs or rhs of ; the predicate. -declare void @goo() -declare void @hoo() +declare void @goo() noconvergent +declare void @hoo() noconvergent define void @test3(i32 %m, i32** %t1) { L1: Index: llvm/test/Transforms/JumpThreading/pr26096.ll =================================================================== --- llvm/test/Transforms/JumpThreading/pr26096.ll +++ llvm/test/Transforms/JumpThreading/pr26096.ll @@ -65,9 +65,9 @@ ret void } -declare void @__assert_fail(i8*) +declare void @__assert_fail(i8*) noconvergent ; Function Attrs: noreturn nounwind declare void @llvm.trap() #0 -attributes #0 = { noreturn nounwind } +attributes #0 = { noconvergent noreturn nounwind } Index: llvm/test/Transforms/JumpThreading/pr27840.ll =================================================================== --- llvm/test/Transforms/JumpThreading/pr27840.ll +++ llvm/test/Transforms/JumpThreading/pr27840.ll @@ -3,8 +3,8 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" -declare void @helper() -declare i32 @__gxx_personality_v0(...) +declare void @helper() noconvergent +declare i32 @__gxx_personality_v0(...) noconvergent define void @pr27840(i8* %call, i1 %A) personality i32(...)* @__gxx_personality_v0 { Index: llvm/test/Transforms/JumpThreading/pr33917.ll =================================================================== --- llvm/test/Transforms/JumpThreading/pr33917.ll +++ llvm/test/Transforms/JumpThreading/pr33917.ll @@ -4,9 +4,9 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -declare i8* @foo() +declare i8* @foo() noconvergent -declare i32 @rust_eh_personality() unnamed_addr +declare i32 @rust_eh_personality() unnamed_addr noconvergent ; Function Attrs: nounwind declare void @llvm.assume(i1) #0 Index: llvm/test/Transforms/JumpThreading/range-compare.ll =================================================================== --- llvm/test/Transforms/JumpThreading/range-compare.ll +++ llvm/test/Transforms/JumpThreading/range-compare.ll @@ -2,8 +2,8 @@ ;RUN: opt < %s -jump-threading -S | FileCheck %s -declare void @bar(...) -declare void @baz(...) +declare void @bar(...) noconvergent +declare void @baz(...) noconvergent ; Make sure we thread the end of the bar block to the end of the function. define void @test1(i32 %x) { Index: llvm/test/Transforms/JumpThreading/select.ll =================================================================== --- llvm/test/Transforms/JumpThreading/select.ll +++ llvm/test/Transforms/JumpThreading/select.ll @@ -1,9 +1,9 @@ ; RUN: opt -S -jump-threading < %s | FileCheck %s -declare void @foo() -declare void @bar() -declare void @baz() -declare void @quux() +declare void @foo() noconvergent +declare void @bar() noconvergent +declare void @baz() noconvergent +declare void @quux() noconvergent ; Jump threading of branch with select as condition. Index: llvm/test/Transforms/JumpThreading/stale-loop-info-after-unfold-select.ll =================================================================== --- llvm/test/Transforms/JumpThreading/stale-loop-info-after-unfold-select.ll +++ llvm/test/Transforms/JumpThreading/stale-loop-info-after-unfold-select.ll @@ -26,5 +26,5 @@ br label %while.cond } -declare i32 @func3(i32, i32, i32) +declare i32 @func3(i32, i32, i32) noconvergent Index: llvm/test/Transforms/JumpThreading/static-profile.ll =================================================================== --- llvm/test/Transforms/JumpThreading/static-profile.ll +++ llvm/test/Transforms/JumpThreading/static-profile.ll @@ -71,7 +71,7 @@ ; As a result, the loop exit edge ends up with 0 frequency which in turn makes ; the loop header to have maximum frequency. -declare void @bar() +declare void @bar() noconvergent define void @foo(i32 *%p, i32 %n) !prof !0 { entry: Index: llvm/test/Transforms/JumpThreading/thread-cmp.ll =================================================================== --- llvm/test/Transforms/JumpThreading/thread-cmp.ll +++ llvm/test/Transforms/JumpThreading/thread-cmp.ll @@ -1,5 +1,5 @@ ; RUN: opt -S -jump-threading %s | FileCheck %s -; When simplify a branch based on LVI predicates, we should replace the +; When simplify a branch based on LVI predicates, we should replace the ; comparison itself with a constant (when possible) in case it's otherwise used. define i32 @test(i32* %p) { @@ -22,9 +22,9 @@ ret i32 1 } -declare void @use(i1) +declare void @use(i1) noconvergent -; It would not be legal to replace %cmp2 (well, in this case it actually is, +; It would not be legal to replace %cmp2 (well, in this case it actually is, ; but that's a CSE problem, not a LVI/jump threading problem) define i32 @test_negative(i32* %p) { ; CHECK-LABEL: @test Index: llvm/test/Transforms/JumpThreading/thread-loads.ll =================================================================== --- llvm/test/Transforms/JumpThreading/thread-loads.ll +++ llvm/test/Transforms/JumpThreading/thread-loads.ll @@ -6,7 +6,7 @@ ; Test that we can thread through the block with the partially redundant load (%2). ; rdar://6402033 -define i32 @test1(i32* %P) nounwind { +define i32 @test1(i32* %P) noconvergent nounwind { ; CHECK-LABEL: @test1( entry: %0 = tail call i32 (...) @f1() nounwind ; [#uses=1] @@ -37,15 +37,15 @@ ret i32 %res.0 } -declare i32 @f1(...) +declare i32 @f1(...) noconvergent -declare i32 @f2(...) +declare i32 @f2(...) noconvergent ;; Check that we preserve TBAA information. ; rdar://11039258 -define i32 @test2(i32* %P) nounwind { +define i32 @test2(i32* %P) noconvergent nounwind { ; CHECK-LABEL: @test2( entry: %0 = tail call i32 (...) @f1() nounwind ; [#uses=1] @@ -76,7 +76,7 @@ ret i32 %res.0 } -define i32 @test3(i8** %x, i1 %f) { +define i32 @test3(i8** %x, i1 %f) noconvergent { ; Correctly thread loads of different (but compatible) types, placing bitcasts ; as necessary in the predecessors. This is especially tricky because the same ; predecessor ends up with two entries in the PHI node and they must share @@ -107,7 +107,7 @@ ret i32 13 } -define i32 @test4(i32* %P) { +define i32 @test4(i32* %P) noconvergent { ; CHECK-LABEL: @test4( entry: %v0 = tail call i32 (...) @f1() @@ -138,7 +138,7 @@ ret i32 %res.0 } -define i32 @test5(i32* %P) { +define i32 @test5(i32* %P) noconvergent { ; Negative test ; CHECK-LABEL: @test5( @@ -174,7 +174,7 @@ ret i32 %res.0 } -define i32 @test6(i32* %P) { +define i32 @test6(i32* %P) noconvergent { ; Negative test ; CHECK-LABEL: @test6( @@ -210,7 +210,7 @@ ret i32 %res.0 } -define i32 @test7(i32* %P) { +define i32 @test7(i32* %P) noconvergent { ; Negative test ; CHECK-LABEL: @test7( @@ -249,7 +249,7 @@ ; Make sure we merge the aliasing metadata. We keep the range metadata for the ; first load, as it dominates the second load. Hence we can eliminate the ; branch. -define void @test8(i32*, i32*, i32*) { +define void @test8(i32*, i32*, i32*) noconvergent{ ; CHECK-LABEL: @test8( ; CHECK: %a = load i32, i32* %0, !range ![[RANGE4:[0-9]+]] ; CHECK-NEXT: store i32 %a @@ -272,7 +272,7 @@ ; Make sure we merge/PRE aliasing metadata correctly. That means that ; we need to remove metadata from the existing load, and add appropriate ; metadata to the newly inserted load. -define void @test9(i32*, i32*, i32*, i1 %c) { +define void @test9(i32*, i32*, i32*, i1 %c) noconvergent { ; CHECK-LABEL: @test9( br i1 %c, label %d1, label %d2 @@ -304,7 +304,7 @@ ret void } -define i32 @fn_noalias(i1 %c2,i64* noalias %P, i64* noalias %P2) { +define i32 @fn_noalias(i1 %c2,i64* noalias %P, i64* noalias %P2) noconvergent { ; CHECK-LABEL: @fn_noalias ; CHECK-LABEL: cond1: ; CHECK: %[[LD1:.*]] = load i64, i64* %P @@ -346,7 +346,7 @@ @current_move = internal global [65 x i32] zeroinitializer, align 4 @last = internal unnamed_addr global [65 x i32*] zeroinitializer, align 8 @next_status = internal unnamed_addr global [65 x %struct.NEXT_MOVE] zeroinitializer, align 8 -define fastcc i32 @Search(i64 %idxprom.i, i64 %idxprom.i89, i32 %c) { +define fastcc i32 @Search(i64 %idxprom.i, i64 %idxprom.i89, i32 %c) noconvergent { ; CHECK-LABEL: @Search ; CHECK-LABEL: sw.bb.i: ; CHECK: %[[LD1:.*]] = load i32, i32* %arrayidx185, align 4 @@ -407,13 +407,13 @@ ret i32 0 } -declare fastcc i32* @GenerateCheckEvasions() -declare fastcc i32 @ValidMove(i32 %move) -declare void @f67() -declare void @Cleanup() -declare void @f65() +declare fastcc i32* @GenerateCheckEvasions() noconvergent +declare fastcc i32 @ValidMove(i32 %move) noconvergent +declare void @f67() noconvergent +declare void @Cleanup() noconvergent +declare void @f65() noconvergent -define i32 @fn_SinglePred(i1 %c2,i64* %P) { +define i32 @fn_SinglePred(i1 %c2,i64* %P) noconvergent { ; CHECK-LABEL: @fn_SinglePred ; CHECK-LABEL: entry: ; CHECK: %[[L1:.*]] = load i64, i64* %P @@ -449,7 +449,7 @@ ret i32 0 } -define i32 @fn_SinglePredMultihop(i1 %c1, i1 %c2,i64* %P) { +define i32 @fn_SinglePredMultihop(i1 %c1, i1 %c2,i64* %P) noconvergent { ; CHECK-LABEL: @fn_SinglePredMultihop ; CHECK-LABEL: entry: ; CHECK: %[[L1:.*]] = load i64, i64* %P @@ -488,8 +488,8 @@ ret i32 0 } -declare void @fn2(i64) -declare void @fn3(i64) +declare void @fn2(i64) noconvergent +declare void @fn3(i64) noconvergent ; Make sure we phi-translate and make the partially redundant load in @@ -503,7 +503,7 @@ ; ; CHECK: left_x: ; CHECK-NEXT: ret i32 20 -define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*) { +define i32 @phi_translate_partial_redundant_loads(i32, i32*, i32*) noconvergent { %cmp0 = icmp ne i32 %0, 0 br i1 %cmp0, label %left, label %right Index: llvm/test/Transforms/JumpThreading/threading_prof1.ll =================================================================== --- llvm/test/Transforms/JumpThreading/threading_prof1.ll +++ llvm/test/Transforms/JumpThreading/threading_prof1.ll @@ -35,24 +35,24 @@ br i1 %tmp1, label %bb5_1, label %bb2 ; CHECK: br i1 %tmp1,{{.*}} !prof ![[PROF1:[0-9]+]] -bb5_1: +bb5_1: br label %bb5; -bb2: +bb2: %tmp3 = call i32 @b() %tmp4 = icmp ne i32 %tmp3, 1 br label %bb5 ; CHECK: br i1 %tmp4, {{.*}} !prof ![[PROF2:[0-9]+]] -bb5: +bb5: %tmp6 = phi i1 [ false, %bb5_1 ], [ %tmp4, %bb2 ] br i1 %tmp6, label %bb8, label %bb7, !prof !0 -bb7: +bb7: call void @bar() br label %bb8 -bb8: +bb8: ret void } @@ -64,35 +64,35 @@ br i1 %tmp1, label %bb5_1, label %bb2 ; CHECK: br i1 %tmp1,{{.*}} !prof ![[PROF1:[0-9]+]] -bb5_1: +bb5_1: br label %bb5_2; -bb5_2: +bb5_2: br label %bb5; -bb2: +bb2: %tmp3 = call i32 @b() %tmp4 = icmp ne i32 %tmp3, 1 br label %bb5 ; CHECK: br i1 %tmp4, {{.*}} !prof ![[PROF2:[0-9]+]] -bb5: +bb5: %tmp6 = phi i1 [ false, %bb5_2 ], [ %tmp4, %bb2 ] br i1 %tmp6, label %bb8, label %bb7, !prof !0 -bb7: +bb7: call void @bar() br label %bb8 -bb8: +bb8: ret void } -declare void @bar() +declare void @bar() noconvergent -declare i32 @a() +declare i32 @a() noconvergent -declare i32 @b() +declare i32 @b() noconvergent !0 = !{!"branch_weights", i32 2146410443, i32 1073205} ;CHECK: ![[PROF1]] = !{!"branch_weights", i32 1073205, i32 2146410443} Index: llvm/test/Transforms/JumpThreading/threading_prof2.ll =================================================================== --- llvm/test/Transforms/JumpThreading/threading_prof2.ll +++ llvm/test/Transforms/JumpThreading/threading_prof2.ll @@ -7,35 +7,35 @@ br i1 %tmp1, label %bb5, label %bb2 ; CHECK: br i1 %tmp1,{{.*}} !prof ![[PROF1:[0-9]+]] -bb2: +bb2: %tmp3 = call i32 @b() %tmp4 = icmp ne i32 %tmp3, 1 br label %bb5 ; CHECK: br i1 %tmp4, {{.*}} !prof ![[PROF2:[0-9]+]] -bb5: +bb5: %tmp6 = phi i1 [ false, %bb ], [ %tmp4, %bb2 ] br i1 %tmp6, label %bb8, label %bb7, !prof !0 -bb7: +bb7: call void @bar() br label %bb9 -bb8: +bb8: call void @foo() br label %bb9 -bb9: +bb9: ret void } -declare void @bar() +declare void @bar() noconvergent -declare void @foo() +declare void @foo() noconvergent -declare i32 @a() +declare i32 @a() noconvergent -declare i32 @b() +declare i32 @b() noconvergent !0 = !{!"branch_weights", i32 2146410443, i32 1073205} ;CHECK: ![[PROF1]] = !{!"branch_weights", i32 1073205, i32 2146410443} Index: llvm/test/Transforms/JumpThreading/unreachable-loops.ll =================================================================== --- llvm/test/Transforms/JumpThreading/unreachable-loops.ll +++ llvm/test/Transforms/JumpThreading/unreachable-loops.ll @@ -58,6 +58,6 @@ bb8: ; preds = %bb8, %bb7, %bb5, %bb2 ret void } -declare i32 @a() +declare i32 @a() noconvergent !0 = !{!"branch_weights", i32 2146410443, i32 1073205} Index: llvm/test/Transforms/JumpThreading/update-edge-weight.ll =================================================================== --- llvm/test/Transforms/JumpThreading/update-edge-weight.ll +++ llvm/test/Transforms/JumpThreading/update-edge-weight.ll @@ -33,10 +33,10 @@ ret void } -declare void @a() -declare void @b() -declare void @c() -declare void @d() +declare void @a() noconvergent +declare void @b() noconvergent +declare void @c() noconvergent +declare void @d() noconvergent !0 = !{!"function_entry_count", i64 1} !1 = !{!"branch_weights", i32 10, i32 5} Index: llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll =================================================================== --- llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll +++ llvm/test/Transforms/LoopDistribute/basic-with-memchecks.ll @@ -281,8 +281,8 @@ ret void } -attributes #0 = { nounwind readnone convergent } -attributes #1 = { nounwind convergent } +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } !0 = distinct !{!0, !1} !1 = !{!"llvm.loop.distribute.enable", i1 true} Index: llvm/test/Transforms/LoopRotate/convergent.ll =================================================================== --- llvm/test/Transforms/LoopRotate/convergent.ll +++ llvm/test/Transforms/LoopRotate/convergent.ll @@ -3,8 +3,8 @@ @e = global i32 10 -declare void @f1(i32) convergent -declare void @f2(i32) +declare void @f1(i32) +declare void @f2(i32) noconvergent ; The call to f1 in the loop header shouldn't be duplicated (meaning, loop ; rotation shouldn't occur), because f1 is convergent. Index: llvm/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll +++ llvm/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll @@ -1,7 +1,7 @@ ; RUN: opt < %s -loop-unroll -S -unroll-count=4 | FileCheck %s ; Test phi update after partial unroll. -declare i1 @check() nounwind +declare i1 @check() noconvergent nounwind ; CHECK: @test ; CHECK: if.else: Index: llvm/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll +++ llvm/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll @@ -6,8 +6,8 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-macosx10.6.8" -declare i1 @check() nounwind -declare i32 @getval() nounwind +declare i1 @check() noconvergent nounwind +declare i32 @getval() noconvergent nounwind ; Check that the loop exit merges values from all the iterations. This ; could be a tad fragile, but it's a good test. Index: llvm/test/Transforms/LoopUnroll/convergent.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/convergent.ll +++ llvm/test/Transforms/LoopUnroll/convergent.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s -declare void @f() convergent +declare void @f() ; Although this loop contains a convergent instruction, it should be ; fully unrolled. @@ -42,7 +42,7 @@ ; CHECK: call void @f() ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, %loop_ctl br i1 %exitcond, label %exit, label %l3 @@ -71,7 +71,7 @@ ; CHECK: call void @f() ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, %loop_ctl br i1 %exitcond, label %exit, label %l3, !llvm.loop !0 @@ -92,7 +92,7 @@ ; CHECK: call void @f() ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, 4 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 @@ -114,7 +114,7 @@ ; CHECK: call void @f() ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, %loop_ctl br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 @@ -137,7 +137,7 @@ %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ] ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, %n br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 @@ -165,7 +165,7 @@ ; CHECK: call void @f() ; CHECK: call void @f() ; CHECK-NOT: call void @f() - call void @f() convergent + call void @f() ; convergent %inc = add nsw i32 %x.0, 1 %exitcond = icmp eq i32 %inc, 5 br i1 %exitcond, label %exit, label %l3, !llvm.loop !1 @@ -176,4 +176,3 @@ !0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}} !1 = !{!1, !{!"llvm.loop.unroll.count", i32 2}} - Index: llvm/test/Transforms/LoopUnroll/loop-remarks-with-hotness.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/loop-remarks-with-hotness.ll +++ llvm/test/Transforms/LoopUnroll/loop-remarks-with-hotness.ll @@ -22,7 +22,7 @@ ret i32 %add1 } -declare i32 @baz(i32) +declare i32 @baz(i32) noconvergent !0 = !{!"function_entry_count", i64 3} !1 = !{!"branch_weights", i32 1, i32 99} Index: llvm/test/Transforms/LoopUnroll/loop-remarks.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/loop-remarks.ll +++ llvm/test/Transforms/LoopUnroll/loop-remarks.ll @@ -45,4 +45,4 @@ ret i32 %add1 } -declare i32 @baz(i32) \ No newline at end of file +declare i32 @baz(i32) noconvergent Index: llvm/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll =================================================================== --- llvm/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll +++ llvm/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll @@ -603,7 +603,7 @@ ret void } -declare i8 addrspace(1)* @foo(i32) +declare i8 addrspace(1)* @foo(i32) noconvergent ; inner loop prolog unrolled ; a value from outer loop is used in exit block of inner loop. ; Don't create VMap entries for such values (%trip). Index: llvm/test/Transforms/LoopUnswitch/2008-11-03-Invariant.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/2008-11-03-Invariant.ll +++ llvm/test/Transforms/LoopUnswitch/2008-11-03-Invariant.ll @@ -39,4 +39,4 @@ ret i32 0 } -declare i32 @b(...) +declare i32 @b(...) noconvergent Index: llvm/test/Transforms/LoopUnswitch/2011-11-18-SimpleSwitch.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/2011-11-18-SimpleSwitch.ll +++ llvm/test/Transforms/LoopUnswitch/2011-11-18-SimpleSwitch.ll @@ -88,8 +88,8 @@ ret i32 0 } -declare void @incf() noreturn -declare void @decf() noreturn +declare void @incf() noconvergent noreturn +declare void @decf() noconvergent noreturn -; CHECK: attributes #0 = { noreturn } +; CHECK: attributes #0 = { noconvergent noreturn } ; CHECK: attributes [[NOR_NUW]] = { noreturn nounwind } Index: llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll +++ llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches-Threshold.ll @@ -81,8 +81,8 @@ ret i32 0 } -declare void @incf() noreturn -declare void @decf() noreturn +declare void @incf() noconvergent noreturn +declare void @decf() noconvergent noreturn -; CHECK: attributes #0 = { noreturn } +; CHECK: attributes #0 = { noconvergent noreturn } ; CHECK: attributes [[NOR_NUW]] = { noreturn nounwind } Index: llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches.ll +++ llvm/test/Transforms/LoopUnswitch/2011-11-18-TwoSwitches.ll @@ -135,8 +135,8 @@ ret i32 0 } -declare void @incf() noreturn -declare void @decf() noreturn +declare void @incf() noconvergent noreturn +declare void @decf() noconvergent noreturn -; CHECK: attributes #0 = { noreturn } +; CHECK: attributes #0 = { noconvergent noreturn } ; CHECK: attributes [[NOR_NUW]] = { noreturn nounwind } Index: llvm/test/Transforms/LoopUnswitch/basictest.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/basictest.ll +++ llvm/test/Transforms/LoopUnswitch/basictest.ll @@ -51,12 +51,12 @@ ] inc: - call void @incf() noreturn nounwind + call void @incf() noconvergent noreturn nounwind br label %loop_begin dec: ; CHECK: call void @decf() ; CHECK-NOT: call void @decf() - call void @decf() noreturn nounwind noduplicate + call void @decf() noconvergent noreturn nounwind noduplicate br label %loop_begin default: br label %loop_exit @@ -82,7 +82,7 @@ ; CHECK: call void @conv() ; CHECK-NOT: call void @conv() - call void @conv() convergent + call void @conv() switch i32 %c, label %default [ i32 1, label %inc @@ -90,10 +90,10 @@ ] inc: - call void @incf() noreturn nounwind + call void @incf() noconvergent noreturn nounwind br label %loop_begin dec: - call void @decf() noreturn nounwind + call void @decf() noconvergent noreturn nounwind br label %loop_begin default: br label %loop_exit @@ -139,7 +139,7 @@ for.inc: %inc = add nsw i2 %i, 1 - %cmp = icmp slt i2 %inc, 3 + %cmp = icmp slt i2 %inc, 3 br i1 %cmp, label %for.body, label %for.end for.end: @@ -183,7 +183,7 @@ for.inc: %inc = add nsw i2 %i, 1 - %cmp = icmp slt i2 %inc, 3 + %cmp = icmp slt i2 %inc, 3 br i1 %cmp, label %for.body, label %for.end for.end: @@ -229,7 +229,7 @@ for.inc: %inc = add nsw i2 %i, 1 - %cmp = icmp slt i2 %inc, 3 + %cmp = icmp slt i2 %inc, 3 br i1 %cmp, label %for.body, label %for.end for.end: @@ -250,7 +250,7 @@ for.body: %i = phi i2 [ 0, %entry ], [ %inc, %for.inc ] - %and = and i2 %a, %i + %and = and i2 %a, %i %or = or i2 %and, %i switch i2 %or, label %sw.default [ i2 0, label %sw.bb @@ -271,7 +271,7 @@ for.inc: %inc = add nsw i2 %i, 1 - %cmp = icmp slt i2 %inc, 3 + %cmp = icmp slt i2 %inc, 3 br i1 %cmp, label %for.body, label %for.end for.end: @@ -292,7 +292,7 @@ for.body: %i = phi i1 [ 0, %entry ], [ %inc, %for.inc ] - %and = and i1 %a, %i + %and = and i1 %a, %i %or = or i1 %and, %i br i1 %or, label %sw.bb, label %sw.bb1 @@ -307,13 +307,13 @@ for.inc: %inc = add nsw i1 %i, 1 - %cmp = icmp slt i1 %inc, 1 + %cmp = icmp slt i1 %inc, 1 br i1 %cmp, label %for.body, label %for.end for.end: ret void } -declare void @incf() noreturn -declare void @decf() noreturn -declare void @conv() convergent +declare void @incf() noconvergent noreturn +declare void @decf() noconvergent noreturn +declare void @conv() Index: llvm/test/Transforms/LoopUnswitch/simplify-with-nonvalness.ll =================================================================== --- llvm/test/Transforms/LoopUnswitch/simplify-with-nonvalness.ll +++ llvm/test/Transforms/LoopUnswitch/simplify-with-nonvalness.ll @@ -56,4 +56,4 @@ ret void } -declare void @bar(...) +declare void @bar(...) noconvergent Index: llvm/test/Transforms/LoopVectorize/ARM/arm-ieee-vectorize.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/ARM/arm-ieee-vectorize.ll +++ llvm/test/Transforms/LoopVectorize/ARM/arm-ieee-vectorize.ll @@ -329,7 +329,7 @@ ret void } -declare float @fabsf(float) +declare float @fabsf(float) noconvergent attributes #1 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a8" "target-features"="+dsp,+neon,+vfp3" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #2 = { nounwind readnone "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a8" "target-features"="+dsp,+neon,+vfp3" "unsafe-fp-math"="true" "use-soft-float"="false" } Index: llvm/test/Transforms/LoopVectorize/PowerPC/massv-calls.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/PowerPC/massv-calls.ll +++ llvm/test/Transforms/LoopVectorize/PowerPC/massv-calls.ll @@ -1,6 +1,6 @@ ; RUN: opt -vector-library=MASSV -loop-vectorize -force-vector-interleave=1 -S < %s | FileCheck %s -target datalayout = "e-m:e-i64:64-n32:64" +target datalayout = "e-m:e-i64:64-n32:64" target triple = "powerpc64le-unknown-linux-gnu" declare double @cbrt(double) #0 @@ -1522,4 +1522,4 @@ ret void } -attributes #0 = { nounwind } +attributes #0 = { noconvergent nounwind } Index: llvm/test/Transforms/LoopVectorize/X86/svml-calls-finite.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/X86/svml-calls-finite.ll +++ llvm/test/Transforms/LoopVectorize/X86/svml-calls-finite.ll @@ -182,6 +182,8 @@ ret void } +attributes #0 = { noconvergent nounwind readnone } + !51 = distinct !{!51, !52, !53} !52 = !{!"llvm.loop.vectorize.width", i32 4} !53 = !{!"llvm.loop.vectorize.enable", i1 true} Index: llvm/test/Transforms/LoopVectorize/X86/svml-calls.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/X86/svml-calls.ll +++ llvm/test/Transforms/LoopVectorize/X86/svml-calls.ll @@ -497,5 +497,5 @@ ret void } -attributes #0 = { nounwind readnone } +attributes #0 = { noconvergent nounwind readnone } Index: llvm/test/Transforms/LoopVectorize/X86/veclib-calls.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/X86/veclib-calls.ll +++ llvm/test/Transforms/LoopVectorize/X86/veclib-calls.ll @@ -6,7 +6,7 @@ ;CHECK-LABEL: @sqrt_f32( ;CHECK: vsqrtf{{.*}}<4 x float> ;CHECK: ret void -declare float @sqrtf(float) nounwind readnone +declare float @sqrtf(float) noconvergent nounwind readnone define void @sqrt_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -31,7 +31,7 @@ ;CHECK-LABEL: @exp_f32( ;CHECK: vexpf{{.*}}<4 x float> ;CHECK: ret void -declare float @expf(float) nounwind readnone +declare float @expf(float) noconvergent nounwind readnone define void @exp_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -56,7 +56,7 @@ ;CHECK-LABEL: @log_f32( ;CHECK: vlogf{{.*}}<4 x float> ;CHECK: ret void -declare float @logf(float) nounwind readnone +declare float @logf(float) noconvergent nounwind readnone define void @log_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -82,7 +82,7 @@ ;CHECK-LABEL: @fabs_f32( ;CHECK: fabs{{.*}}<4 x float> ;CHECK: ret void -declare float @fabsf(float) nounwind readnone +declare float @fabsf(float) noconvergent nounwind readnone define void @fabs_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -108,7 +108,7 @@ ;CHECK-LABEL: @exp_f32_intrin( ;CHECK: vexpf{{.*}}<4 x float> ;CHECK: ret void -declare float @llvm.exp.f32(float) nounwind readnone +declare float @llvm.exp.f32(float) noconvergent nounwind readnone define void @exp_f32_intrin(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -134,7 +134,7 @@ ;CHECK-LABEL: @foo_f32( ;CHECK-NOT: foo{{.*}}<4 x float> ;CHECK: ret void -declare float @foo(float) nounwind readnone +declare float @foo(float) noconvergent nounwind readnone define void @foo_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -184,7 +184,7 @@ ;CHECK-LABEL: @ceil_f32( ;CHECK: vceilf{{.*}}<4 x float> ;CHECK: ret void -declare float @ceilf(float) nounwind readnone +declare float @ceilf(float) noconvergent nounwind readnone define void @ceil_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -209,7 +209,7 @@ ;CHECK-LABEL: @floor_f32( ;CHECK: vfloorf{{.*}}<4 x float> ;CHECK: ret void -declare float @floorf(float) nounwind readnone +declare float @floorf(float) noconvergent nounwind readnone define void @floor_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -234,7 +234,7 @@ ;CHECK-LABEL: @expm1_f32( ;CHECK: vexpm1f{{.*}}<4 x float> ;CHECK: ret void -declare float @expm1f(float) nounwind readnone +declare float @expm1f(float) noconvergent nounwind readnone define void @expm1_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -259,7 +259,7 @@ ;CHECK-LABEL: @log1p_f32( ;CHECK: vlog1pf{{.*}}<4 x float> ;CHECK: ret void -declare float @log1pf(float) nounwind readnone +declare float @log1pf(float) noconvergent nounwind readnone define void @log1p_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -284,7 +284,7 @@ ;CHECK-LABEL: @log10_f32( ;CHECK: vlog10f{{.*}}<4 x float> ;CHECK: ret void -declare float @log10f(float) nounwind readnone +declare float @log10f(float) noconvergent nounwind readnone define void @log10_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -309,7 +309,7 @@ ;CHECK-LABEL: @logb_f32( ;CHECK: vlogbf{{.*}}<4 x float> ;CHECK: ret void -declare float @logbf(float) nounwind readnone +declare float @logbf(float) noconvergent nounwind readnone define void @logb_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -334,7 +334,7 @@ ;CHECK-LABEL: @sin_f32( ;CHECK: vsinf{{.*}}<4 x float> ;CHECK: ret void -declare float @sinf(float) nounwind readnone +declare float @sinf(float) noconvergent nounwind readnone define void @sin_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -359,7 +359,7 @@ ;CHECK-LABEL: @cos_f32( ;CHECK: vcosf{{.*}}<4 x float> ;CHECK: ret void -declare float @cosf(float) nounwind readnone +declare float @cosf(float) noconvergent nounwind readnone define void @cos_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -384,7 +384,7 @@ ;CHECK-LABEL: @tan_f32( ;CHECK: vtanf{{.*}}<4 x float> ;CHECK: ret void -declare float @tanf(float) nounwind readnone +declare float @tanf(float) noconvergent nounwind readnone define void @tan_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -409,7 +409,7 @@ ;CHECK-LABEL: @asin_f32( ;CHECK: vasinf{{.*}}<4 x float> ;CHECK: ret void -declare float @asinf(float) nounwind readnone +declare float @asinf(float) noconvergent nounwind readnone define void @asin_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -434,7 +434,7 @@ ;CHECK-LABEL: @acos_f32( ;CHECK: vacosf{{.*}}<4 x float> ;CHECK: ret void -declare float @acosf(float) nounwind readnone +declare float @acosf(float) noconvergent nounwind readnone define void @acos_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -459,7 +459,7 @@ ;CHECK-LABEL: @atan_f32( ;CHECK: vatanf{{.*}}<4 x float> ;CHECK: ret void -declare float @atanf(float) nounwind readnone +declare float @atanf(float) noconvergent nounwind readnone define void @atan_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -484,7 +484,7 @@ ;CHECK-LABEL: @sinh_f32( ;CHECK: vsinhf{{.*}}<4 x float> ;CHECK: ret void -declare float @sinhf(float) nounwind readnone +declare float @sinhf(float) noconvergent nounwind readnone define void @sinh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -509,7 +509,7 @@ ;CHECK-LABEL: @cosh_f32( ;CHECK: vcoshf{{.*}}<4 x float> ;CHECK: ret void -declare float @coshf(float) nounwind readnone +declare float @coshf(float) noconvergent nounwind readnone define void @cosh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -534,7 +534,7 @@ ;CHECK-LABEL: @tanh_f32( ;CHECK: vtanhf{{.*}}<4 x float> ;CHECK: ret void -declare float @tanhf(float) nounwind readnone +declare float @tanhf(float) noconvergent nounwind readnone define void @tanh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -559,7 +559,7 @@ ;CHECK-LABEL: @asinh_f32( ;CHECK: vasinhf{{.*}}<4 x float> ;CHECK: ret void -declare float @asinhf(float) nounwind readnone +declare float @asinhf(float) noconvergent nounwind readnone define void @asinh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -584,7 +584,7 @@ ;CHECK-LABEL: @acosh_f32( ;CHECK: vacoshf{{.*}}<4 x float> ;CHECK: ret void -declare float @acoshf(float) nounwind readnone +declare float @acoshf(float) noconvergent nounwind readnone define void @acosh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 @@ -609,7 +609,7 @@ ;CHECK-LABEL: @atanh_f32( ;CHECK: vatanhf{{.*}}<4 x float> ;CHECK: ret void -declare float @atanhf(float) nounwind readnone +declare float @atanhf(float) noconvergent nounwind readnone define void @atanh_f32(i32 %n, float* noalias %y, float* noalias %x) nounwind uwtable { entry: %cmp6 = icmp sgt i32 %n, 0 Index: llvm/test/Transforms/MemCpyOpt/memcpy.ll =================================================================== --- llvm/test/Transforms/MemCpyOpt/memcpy.ll +++ llvm/test/Transforms/MemCpyOpt/memcpy.ll @@ -248,6 +248,6 @@ declare void @f2(%struct.big*) ; CHECK: attributes [[$NUW]] = { nounwind } -; CHECK: attributes #1 = { argmemonly nounwind willreturn } +; CHECK: attributes #1 = { argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #2 = { nounwind ssp } ; CHECK: attributes #3 = { nounwind ssp uwtable } Index: llvm/test/Transforms/ObjCARC/basic.ll =================================================================== --- llvm/test/Transforms/ObjCARC/basic.ll +++ llvm/test/Transforms/ObjCARC/basic.ll @@ -1444,7 +1444,7 @@ ; CHECK: call void @llvm.objc.release ; CHECK: } define void @test27(i8* %p, i1 %x, i1 %y) { -entry: +entry: %f0 = call i8* @llvm.objc.retain(i8* %p) br i1 %x, label %loop, label %done @@ -1452,8 +1452,8 @@ call void @callee() store i8 0, i8* %p br i1 %y, label %done, label %loop - -done: + +done: call void @llvm.objc.release(i8* %p) ret void } @@ -2238,13 +2238,13 @@ ; CHECK-LABEL: define void @test55( ; CHECK-NOT: @objc ; CHECK: } -define void @test55(i8* %x) { -entry: - %0 = call i8* @llvm.objc.retain(i8* %x) nounwind - %1 = call i8* @llvm.objc.retain(i8* %x) nounwind - call void @llvm.objc.release(i8* %x) nounwind - call void @llvm.objc.release(i8* %x) nounwind - ret void +define void @test55(i8* %x) { +entry: + %0 = call i8* @llvm.objc.retain(i8* %x) nounwind + %1 = call i8* @llvm.objc.retain(i8* %x) nounwind + call void @llvm.objc.release(i8* %x) nounwind + call void @llvm.objc.release(i8* %x) nounwind + ret void } ; Nested retain+release pairs where the inner pair depends @@ -3069,6 +3069,7 @@ !4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir") !5 = !{i32 2, !"Debug Info Version", i32 3} +; CHECK: attributes #0 = { noconvergent nounwind } +; CHECK: attributes #1 = { noconvergent nounwind readnone speculatable willreturn } ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nounwind readnone speculatable willreturn } ; CHECK: ![[RELEASE]] = !{} Index: llvm/test/Transforms/ObjCARC/cfg-hazards.ll =================================================================== --- llvm/test/Transforms/ObjCARC/cfg-hazards.ll +++ llvm/test/Transforms/ObjCARC/cfg-hazards.ll @@ -87,7 +87,7 @@ ; Delete nested retain+release pairs around loops. -; CHECK: define void @test3(i8* %a) #0 { +; CHECK: define void @test3(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW:#[0-9]+]] ; CHECK-NEXT: br label %loop @@ -113,7 +113,7 @@ ret void } -; CHECK: define void @test4(i8* %a) #0 { +; CHECK: define void @test4(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: br label %loop @@ -143,7 +143,7 @@ ret void } -; CHECK: define void @test5(i8* %a) #0 { +; CHECK: define void @test5(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: call void @callee() @@ -177,7 +177,7 @@ ret void } -; CHECK: define void @test6(i8* %a) #0 { +; CHECK: define void @test6(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: br label %loop @@ -210,7 +210,7 @@ ret void } -; CHECK: define void @test7(i8* %a) #0 { +; CHECK: define void @test7(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: call void @callee() @@ -243,7 +243,7 @@ ret void } -; CHECK: define void @test8(i8* %a) #0 { +; CHECK: define void @test8(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: br label %loop @@ -275,7 +275,7 @@ ret void } -; CHECK: define void @test9(i8* %a) #0 { +; CHECK: define void @test9(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label %loop ; CHECK-NOT: @llvm.objc. @@ -304,7 +304,7 @@ ret void } -; CHECK: define void @test10(i8* %a) #0 { +; CHECK: define void @test10(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label %loop ; CHECK-NOT: @llvm.objc. @@ -333,7 +333,7 @@ ret void } -; CHECK: define void @test11(i8* %a) #0 { +; CHECK: define void @test11(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label %loop ; CHECK-NOT: @llvm.objc. @@ -363,7 +363,7 @@ ; Don't delete anything if they're not balanced. -; CHECK: define void @test12(i8* %a) #0 { +; CHECK: define void @test12(i8* %a) #1 { ; CHECK-NEXT: entry: ; CHECK-NEXT: %outer = tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] ; CHECK-NEXT: %inner = tail call i8* @llvm.objc.retain(i8* %a) [[NUW]] @@ -424,7 +424,7 @@ %reloaded_a = load i8*, i8** %block, align 8 call void @llvm.objc.release(i8* %reloaded_a) nounwind, !clang.imprecise_release !0 br i1 undef, label %loop, label %exit - + exit: call void @llvm.objc.release(i8* %a) nounwind, !clang.imprecise_release !0 ret void Index: llvm/test/Transforms/ObjCARC/contract-storestrong-funclet.ll =================================================================== --- llvm/test/Transforms/ObjCARC/contract-storestrong-funclet.ll +++ llvm/test/Transforms/ObjCARC/contract-storestrong-funclet.ll @@ -28,10 +28,10 @@ } ; CHECK-LABEL: invoke.cont: -; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #0{{$}} +; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #1{{$}} ; CHECK: ret void ; CHECK-LABEL: ehcleanup: ; CHECK: %1 = cleanuppad within none [] -; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #0 [ "funclet"(token %1) ] +; CHECK: tail call void @llvm.objc.storeStrong(i8** @x, i8* %p) #1 [ "funclet"(token %1) ] ; CHECK: cleanupret from %1 unwind to caller Index: llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll =================================================================== --- llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll +++ llvm/test/Transforms/ObjCARC/ensure-that-exception-unwind-path-is-visited.ll @@ -105,10 +105,10 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { ssp uwtable } -; CHECK: attributes #1 = { nounwind readnone speculatable willreturn } +; CHECK: attributes #1 = { noconvergent nounwind readnone speculatable willreturn } ; CHECK: attributes #2 = { nonlazybind } -; CHECK: attributes [[NUW]] = { nounwind } ; CHECK: attributes #4 = { noinline ssp uwtable } +; CHECK: attributes [[NUW]] = { nounwind } !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!33, !34, !35, !36, !61} Index: llvm/test/Transforms/ObjCARC/escape.ll =================================================================== --- llvm/test/Transforms/ObjCARC/escape.ll +++ llvm/test/Transforms/ObjCARC/escape.ll @@ -131,4 +131,4 @@ !0 = !{} ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nounwind ssp } +; CHECK: attributes #2 = { nounwind ssp } Index: llvm/test/Transforms/ObjCARC/nested.ll =================================================================== --- llvm/test/Transforms/ObjCARC/nested.ll +++ llvm/test/Transforms/ObjCARC/nested.ll @@ -820,6 +820,6 @@ } -; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { argmemonly nounwind willreturn } +; CHECK: attributes #1 = { argmemonly noconvergent nounwind willreturn } ; CHECK: attributes #2 = { nonlazybind } +; CHECK: attributes [[NUW]] = { nounwind } Index: llvm/test/Transforms/ObjCARC/opt-catchswitch.ll =================================================================== --- llvm/test/Transforms/ObjCARC/opt-catchswitch.ll +++ llvm/test/Transforms/ObjCARC/opt-catchswitch.ll @@ -49,6 +49,6 @@ ; CHECK-LABEL: cleanup: ; CHECK: tail call void @llvm.objc.release(i8* %p) #0 -attributes #0 = { nounwind } +attributes #0 = { noconvergent nounwind } !0 = !{} Index: llvm/test/Transforms/ObjCARC/rle-s2l.ll =================================================================== --- llvm/test/Transforms/ObjCARC/rle-s2l.ll +++ llvm/test/Transforms/ObjCARC/rle-s2l.ll @@ -134,5 +134,5 @@ ret void } -; CHECK: attributes #0 = { nounwind } +; CHECK: attributes #0 = { noconvergent nounwind } ; CHECK: attributes [[RO]] = { readonly } Index: llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll =================================================================== --- llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll +++ llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll @@ -308,5 +308,5 @@ ; CHECK: declare i32 @objc_sync_enter(i8*) ; CHECK: declare i32 @objc_sync_exit(i8*) -; CHECK: attributes #0 = { nounwind } +; CHECK: attributes #0 = { noconvergent nounwind } ; CHECK: attributes [[NLB]] = { nonlazybind } Index: llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll =================================================================== --- llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll +++ llvm/test/Transforms/RewriteStatepointsForGC/statepoint-attrs.ll @@ -2,16 +2,16 @@ ; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s ; Ensure statepoints copy (valid) attributes from callsites. -declare void @f(i8 addrspace(1)* %obj) +declare void @f(i8 addrspace(1)* %obj) noconvergent ; copy over norecurse noimplicitfloat to statepoint call define void @test1(i8 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-LABEL: test1( -; CHECK: call token (i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64 2882400000, i32 0, void (i8 addrspace(1)*)* @f, i32 1, i32 0, i8 addrspace(1)* %arg, i32 0, i32 0, i8 addrspace(1)* %arg) #1 +; CHECK: call token (i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64 2882400000, i32 0, void (i8 addrspace(1)*)* @f, i32 1, i32 0, i8 addrspace(1)* %arg, i32 0, i32 0, i8 addrspace(1)* %arg) #2 call void @f(i8 addrspace(1)* %arg) #1 ret void } -attributes #1 = { norecurse noimplicitfloat } +attributes #1 = { norecurse noconvergent noimplicitfloat } Index: llvm/test/Transforms/SLPVectorizer/X86/call.ll =================================================================== --- llvm/test/Transforms/SLPVectorizer/X86/call.ll +++ llvm/test/Transforms/SLPVectorizer/X86/call.ll @@ -173,5 +173,5 @@ ; CHECK: declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) [[ATTR0]] ; CHECK: declare <2 x double> @llvm.exp2.v2f64(<2 x double>) [[ATTR0]] -; CHECK: attributes [[ATTR0]] = { nounwind readnone speculatable willreturn } +; CHECK: attributes [[ATTR0]] = { noconvergent nounwind readnone speculatable willreturn } Index: llvm/test/Transforms/SimpleLoopUnswitch/basictest.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/basictest.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/basictest.ll @@ -82,7 +82,7 @@ ; CHECK: call void @conv() ; CHECK-NOT: call void @conv() - call void @conv() convergent + call void @conv() switch i32 %c, label %default [ i32 1, label %inc @@ -116,7 +116,7 @@ for.body: %i = phi i2 [ 0, %entry ], [ %inc, %for.inc ] - %and = and i2 %a, %i + %and = and i2 %a, %i %or = or i2 %and, %i switch i2 %or, label %sw.default [ i2 0, label %sw.bb @@ -137,7 +137,7 @@ for.inc: %inc = add nsw i2 %i, 1 - %cmp = icmp slt i2 %inc, 3 + %cmp = icmp slt i2 %inc, 3 br i1 %cmp, label %for.body, label %for.end for.end: @@ -158,7 +158,7 @@ for.body: %i = phi i1 [ 0, %entry ], [ %inc, %for.inc ] - %and = and i1 %a, %i + %and = and i1 %a, %i %or = or i1 %and, %i br i1 %or, label %sw.bb, label %sw.bb1 @@ -173,13 +173,13 @@ for.inc: %inc = add nsw i1 %i, 1 - %cmp = icmp slt i1 %inc, 1 + %cmp = icmp slt i1 %inc, 1 br i1 %cmp, label %for.body, label %for.end for.end: ret void } -declare void @incf() noreturn -declare void @decf() noreturn -declare void @conv() convergent +declare void @incf() noconvergent noreturn +declare void @decf() noconvergent noreturn +declare void @conv() Index: llvm/test/Transforms/SimpleLoopUnswitch/delete-dead-blocks.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/delete-dead-blocks.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/delete-dead-blocks.ll @@ -4,7 +4,7 @@ ; ; Checking that (dead) blocks from inner loop are deleted after unswitch. ; -declare void @foo() +declare void @foo() noconvergent ; CHECK-LABEL: @Test define void @Test(i32) { @@ -15,7 +15,7 @@ br label %inner inner: %ii = phi i32 [ 0, %outer ], [ %iinc, %continue] - call void @foo() + call void @foo() switch i32 %0, label %get_out2 [ i32 0, label %continue i32 1, label %case1 Index: llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll @@ -83,7 +83,7 @@ ; LOOP32-COUNT-32: Loop at depth 3 containing: ; LOOP32-NOT: Loop at depth {{[0-9]+}} containing: -declare void @bar() +declare void @bar() noconvergent define void @loop_nested3_conds5(i32* %addr, i1 %c1, i1 %c2, i1 %c3, i1 %c4, i1 %c5) { entry: Index: llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll @@ -95,7 +95,7 @@ ; LOOP-MAX-COUNT-1: Loop at depth 3 containing: ; LOOP-MAX-NOT: Loop at depth 3 containing: -declare void @bar() +declare void @bar() noconvergent define void @loop_nested3_conds5(i32* %addr, i1 %c1, i1 %c2, i1 %c3, i1 %c4, i1 %c5) { entry: Index: llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll @@ -5,9 +5,9 @@ ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S < %s | FileCheck %s ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s -declare void @a() -declare void @b() -declare void @x() +declare void @a() noconvergent +declare void @b() noconvergent +declare void @x() noconvergent ; First establish enough code size in the duplicated 'loop_begin' block to ; suppress unswitching. Index: llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll =================================================================== --- llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll +++ llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll @@ -3,16 +3,18 @@ ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -S < %s | FileCheck %s ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -enable-mssa-loop-dependency=true -verify-memoryssa -S < %s | FileCheck %s -declare i32 @a() -declare i32 @b() -declare i32 @c() -declare i32 @d() +declare i32 @a() noconvergent +declare i32 @b() noconvergent +declare i32 @c() noconvergent +declare i32 @d() noconvergent -declare void @sink1(i32) -declare void @sink2(i32) +declare i32 @convergent() -declare i1 @cond() -declare i32 @cond.i32() +declare void @sink1(i32) noconvergent +declare void @sink2(i32) noconvergent + +declare i1 @cond() noconvergent +declare i32 @cond.i32() noconvergent ; Negative test: we cannot unswitch convergent calls. define void @test_no_unswitch_convergent(i1* %ptr, i1 %cond) { @@ -31,7 +33,7 @@ ; CHECK-NEXT: br i1 %cond, label %loop_a, label %loop_b loop_a: - call i32 @a() convergent + call i32 @convergent() br label %loop_latch loop_b: @@ -78,7 +80,7 @@ ret void } -declare i32 @__CxxFrameHandler3(...) +declare i32 @__CxxFrameHandler3(...) noconvergent ; Negative test: we cannot unswitch when tokens are used across blocks as we ; might introduce PHIs. @@ -2475,9 +2477,9 @@ ; different cloning path from our other test cases and in turn verifying the ; resulting structure can catch any failures to correctly clone these nested ; loops. -declare void @f() -declare void @g() -declare i32 @h(i32 %arg) +declare void @f() noconvergent +declare void @g() noconvergent +declare i32 @h(i32 %arg) noconvergent define void @test22(i32 %arg) { ; CHECK-LABEL: define void @test22( entry: Index: llvm/test/Transforms/SimplifyCFG/attr-convergent.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/attr-convergent.ll +++ llvm/test/Transforms/SimplifyCFG/attr-convergent.ll @@ -1,7 +1,8 @@ ; RUN: opt < %s -simplifycfg -S | FileCheck %s -; Checks that the SimplifyCFG pass won't duplicate a call to a function marked -; convergent. +; Checks that the SimplifyCFG pass won't duplicate a call to a +; potentially convergent function + ; ; CHECK: call void @barrier ; CHECK-NOT: call void @barrier @@ -25,4 +26,4 @@ ret void } -declare void @barrier() convergent +declare void @barrier() Index: llvm/test/Transforms/SimplifyCFG/branch-phi-thread.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/branch-phi-thread.ll +++ llvm/test/Transforms/SimplifyCFG/branch-phi-thread.ll @@ -2,13 +2,13 @@ ; RUN: not grep "call void @f1" ; END. -declare void @f1() +declare void @f1() noconvergent -declare void @f2() +declare void @f2() noconvergent -declare void @f3() +declare void @f3() noconvergent -declare void @f4() +declare void @f4() noconvergent define i32 @test1(i32 %X, i1 %D) { E: Index: llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll +++ llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll @@ -152,7 +152,7 @@ } declare void @llvm.trap() nounwind noreturn -declare void @bees.a() nounwind -declare void @bees.b() nounwind +declare void @bees.a() noconvergent nounwind +declare void @bees.b() noconvergent nounwind -; CHECK: attributes #1 = { cold noreturn nounwind } +; CHECK: attributes #1 = { cold noconvergent noreturn nounwind } Index: llvm/test/Transforms/Sink/call.ll =================================================================== --- llvm/test/Transforms/Sink/call.ll +++ llvm/test/Transforms/Sink/call.ll @@ -1,11 +1,11 @@ ; RUN: opt < %s -basicaa -sink -S | FileCheck %s -declare i32 @f_load_global() nounwind readonly -declare i32 @f_load_arg(i32*) nounwind readonly argmemonly -declare void @f_store_global(i32) nounwind -declare void @f_store_arg(i32*) nounwind argmemonly -declare void @f_readonly_arg(i32* readonly, i32*) nounwind argmemonly -declare i32 @f_readnone(i32) nounwind readnone +declare i32 @f_load_global() noconvergent nounwind readonly +declare i32 @f_load_arg(i32*) noconvergent nounwind readonly argmemonly +declare void @f_store_global(i32) noconvergent nounwind +declare void @f_store_arg(i32*) noconvergent nounwind argmemonly +declare void @f_readonly_arg(i32* readonly, i32*) noconvergent nounwind argmemonly +declare i32 @f_readnone(i32) noconvergent nounwind readnone @A = external global i32 @B = external global i32 Index: llvm/test/Transforms/Sink/convergent.ll =================================================================== --- llvm/test/Transforms/Sink/convergent.ll +++ llvm/test/Transforms/Sink/convergent.ll @@ -10,7 +10,7 @@ define i32 @foo(i1 %arg) { entry: - %c = call i32 @bar() readonly convergent + %c = call i32 @bar() readonly br i1 %arg, label %then, label %end then: @@ -20,4 +20,4 @@ ret i32 0 } -declare i32 @bar() readonly convergent +declare i32 @bar() readonly Index: llvm/test/Transforms/SpeculateAroundPHIs/convergent.ll =================================================================== --- llvm/test/Transforms/SpeculateAroundPHIs/convergent.ll +++ llvm/test/Transforms/SpeculateAroundPHIs/convergent.ll @@ -93,6 +93,6 @@ } -attributes #0 = { nounwind readnone convergent speculatable } +attributes #0 = { nounwind readnone speculatable } attributes #1 = { nounwind readnone noduplicate speculatable } -attributes #2 = { nounwind readnone speculatable } +attributes #2 = { noconvergent nounwind readnone speculatable } Index: llvm/test/Verifier/fp-intrinsics.ll =================================================================== --- llvm/test/Verifier/fp-intrinsics.ll +++ llvm/test/Verifier/fp-intrinsics.ll @@ -12,7 +12,7 @@ ; attached to the FP intrinsic. ; CHECK1: declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) #[[ATTR:[0-9]+]] ; CHECK1: declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata) #[[ATTR]] -; CHECK1: attributes #[[ATTR]] = { inaccessiblememonly nounwind willreturn } +; CHECK1: attributes #[[ATTR]] = { inaccessiblememonly noconvergent nounwind willreturn } ; Note: FP exceptions aren't usually caught through normal unwind mechanisms, ; but we may want to revisit this for asynchronous exception handling. define double @f1(double %a, double %b) #0 { Index: llvm/utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- llvm/utils/TableGen/IntrinsicEmitter.cpp +++ llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -708,7 +708,7 @@ if (!intrinsic.canThrow || (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) || intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold || - intrinsic.isNoDuplicate || intrinsic.isConvergent || + intrinsic.isNoDuplicate || !intrinsic.isConvergent || intrinsic.isSpeculatable) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; @@ -740,10 +740,10 @@ OS << "Attribute::NoDuplicate"; addComma = true; } - if (intrinsic.isConvergent) { + if (!intrinsic.isConvergent) { if (addComma) OS << ","; - OS << "Attribute::Convergent"; + OS << "Attribute::NoConvergent"; addComma = true; } if (intrinsic.isSpeculatable) { Index: llvm/utils/emacs/llvm-mode.el =================================================================== --- llvm/utils/emacs/llvm-mode.el +++ llvm/utils/emacs/llvm-mode.el @@ -22,7 +22,7 @@ (list ;; Attributes `(,(regexp-opt - '("alwaysinline" "argmemonly" "builtin" "cold" "convergent" "inaccessiblememonly" + '("alwaysinline" "argmemonly" "builtin" "cold" "noconvergent" "inaccessiblememonly" "inaccessiblemem_or_argmemonly" "inlinehint" "jumptable" "minsize" "naked" "nobuiltin" "noduplicate" "noimplicitfloat" "noinline" "nonlazybind" "noredzone" "noreturn" "norecurse" "nounwind" "optnone" "optsize" "readnone" "readonly" "returns_twice" Index: llvm/utils/vim/syntax/llvm.vim =================================================================== --- llvm/utils/vim/syntax/llvm.vim +++ llvm/utils/vim/syntax/llvm.vim @@ -112,6 +112,7 @@ \ noalias \ nobuiltin \ nocapture + \ noconvergent \ noimplicitfloat \ noinline \ nonlazybind