Author: Ramkumar Ramachandra Date: 2026-07-18T13:49:40Z New Revision: af0c933eda31b6beb436026a22121ec637f3cb53
URL: https://github.com/llvm/llvm-project/commit/af0c933eda31b6beb436026a22121ec637f3cb53 DIFF: https://github.com/llvm/llvm-project/commit/af0c933eda31b6beb436026a22121ec637f3cb53.diff LOG: [IR] Make semantics of strictfp consistent (#209465) Although the section on constrainedfp in the LangRef clearly states "All function definitions that use constrained floating point intrinsics must have the strictfp attribute", indicating that a function with strictfp calls must be marked with strictfp, the general description of strictfp does not specify this. Refine its semantics and make it so, eliminating the inconsistency. Added: Modified: clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl llvm/docs/LangRef.md llvm/include/llvm/IR/Function.h llvm/lib/IR/Verifier.cpp llvm/test/CodeGen/AArch64/is_fpclass.ll llvm/test/CodeGen/AArch64/sms-loop-carried-fp-exceptions1.mir llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-fp-to-int.ll llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-int-to-fp.ll llvm/test/CodeGen/PowerPC/milicode32.ll llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll llvm/test/CodeGen/RISCV/float-intrinsics-strict.ll llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll llvm/test/CodeGen/RISCV/zfhmin-half-intrinsics-strict.ll llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll llvm/test/Transforms/InstCombine/erf.ll llvm/test/Transforms/InstCombine/fdim.ll llvm/test/Transforms/InstSimplify/disable_folding.ll llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll llvm/unittests/IR/VerifierTest.cpp mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir Removed: ################################################################################ diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 641caf6d5cd4b..2f89154c2d2d9 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -195,6 +195,9 @@ llvm::Value *TargetCodeGenInfo::createEnqueuedBlockKernel( CGF.CGM.addDefaultFunctionDefinitionAttributes(KernelAttrs); F->addFnAttrs(KernelAttrs); + if (CGF.Builder.getIsFPConstrained()) + F->addFnAttr(llvm::Attribute::StrictFP); + auto IP = CGF.Builder.saveIP(); auto *BB = llvm::BasicBlock::Create(C, "entry", F); auto &Builder = CGF.Builder; diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl index 962ac4afa4991..c93f623016660 100644 --- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl +++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl @@ -188,7 +188,7 @@ kernel void device_side_enqueue(global float *a, global float *b, int i) { // STRICTFP-NEXT: ret void // // -// STRICTFP: Function Attrs: convergent nounwind +// STRICTFP: Function Attrs: convergent nounwind strictfp // STRICTFP-LABEL: define spir_kernel void @__device_side_enqueue_block_invoke_kernel( // STRICTFP-SAME: ptr addrspace(4) [[TMP0:%.*]]) #[[ATTR4:[0-9]+]] { // STRICTFP-NEXT: [[ENTRY:.*:]] @@ -207,7 +207,7 @@ kernel void device_side_enqueue(global float *a, global float *b, int i) { // STRICTFP: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // STRICTFP: attributes #[[ATTR2]] = { convergent noinline nounwind optnone strictfp "stack-protector-buffer-size"="8" } // STRICTFP: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite) } -// STRICTFP: attributes #[[ATTR4]] = { convergent nounwind "stack-protector-buffer-size"="8" } +// STRICTFP: attributes #[[ATTR4]] = { convergent nounwind strictfp "stack-protector-buffer-size"="8" } // STRICTFP: attributes #[[ATTR5]] = { convergent nounwind strictfp } // STRICTFP: attributes #[[ATTR6]] = { strictfp } //. diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md index a6b3146cf6749..9526cd020d724 100644 --- a/llvm/docs/LangRef.md +++ b/llvm/docs/LangRef.md @@ -2794,7 +2794,8 @@ fn -> other_fn -> other_fn ; fn is norecurse optimizations that require assumptions about the floating-point rounding mode or that might alter the state of floating-point status flags that might otherwise be set or cleared by calling this function. LLVM will - not introduce any new floating-point instructions that may trap. + not introduce any new floating-point instructions that may trap. All + function definitions that contain strictfp calls must be marked strictfp. (denormal_fpenv)= @@ -26587,9 +26588,6 @@ point intrinsics must have the `strictfp` attribute either on the calling instruction or on the declaration or definition of the function being called. -All function *definitions* that use constrained floating point intrinsics -must have the `strictfp` attribute. - #### '`llvm.experimental.constrained.fadd`' Intrinsic ##### Syntax: diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index bd28f0d9902da..0238c9b352f5f 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -632,6 +632,9 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> { addFnAttr(Attribute::NoRecurse); } + /// Determine if the function has strict floating point sematics. + bool isStrictFP() const { return hasFnAttribute(Attribute::StrictFP); } + /// Determine if the function is required to make forward progress. bool mustProgress() const { return hasFnAttribute(Attribute::MustProgress) || diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index b6ee0170904e8..d315372c1371c 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3889,6 +3889,11 @@ void Verifier::visitCallBase(CallBase &Call) { Check(!Attrs.hasFnAttr(Attribute::DenormalFPEnv), "denormal_fpenv attribute may not apply to call sites", Call); + Check(!Attrs.hasFnAttr(Attribute::StrictFP) || + Call.getFunction()->isStrictFP(), + "call site marked strictfp without caller function marked strictfp", + Call); + // Verify call attributes. verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic, Call.isInlineAsm()); diff --git a/llvm/test/CodeGen/AArch64/is_fpclass.ll b/llvm/test/CodeGen/AArch64/is_fpclass.ll index 71a8f42a7b4db..19ce95641fe98 100644 --- a/llvm/test/CodeGen/AArch64/is_fpclass.ll +++ b/llvm/test/CodeGen/AArch64/is_fpclass.ll @@ -249,7 +249,7 @@ entry: ret i1 %0 } -define i1 @isfinite_d_strictfp(double %x) { +define i1 @isfinite_d_strictfp(double %x) strictfp { ; CHECK-SD-LABEL: isfinite_d_strictfp: ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fmov x8, d0 @@ -278,7 +278,7 @@ entry: ret i1 %0 } -define i1 @not_isfinite_d_strictfp(double %x) { +define i1 @not_isfinite_d_strictfp(double %x) strictfp { ; CHECK-SD-LABEL: not_isfinite_d_strictfp: ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fmov x8, d0 diff --git a/llvm/test/CodeGen/AArch64/sms-loop-carried-fp-exceptions1.mir b/llvm/test/CodeGen/AArch64/sms-loop-carried-fp-exceptions1.mir index 878f7b782a9a1..4d3552a056df5 100644 --- a/llvm/test/CodeGen/AArch64/sms-loop-carried-fp-exceptions1.mir +++ b/llvm/test/CodeGen/AArch64/sms-loop-carried-fp-exceptions1.mir @@ -23,7 +23,7 @@ --- | @x = dso_local global i32 0, align 4 - define dso_local void @f(ptr nocapture noundef writeonly %a, float noundef %y, i32 noundef %n) { + define dso_local void @f(ptr nocapture noundef writeonly %a, float noundef %y, i32 noundef %n) #2 { entry: %cmp6 = icmp sgt i32 %n, 0 br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-fp-to-int.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-fp-to-int.ll index cfdc1baf8c282..9320908403679 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-fp-to-int.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-fp-to-int.ll @@ -209,7 +209,7 @@ define i64 @f64_to_u64(double %x) { ret i64 %cvt } -define i32 @strict_convert_signed(double %x) { +define i32 @strict_convert_signed(double %x) #0 { ; CHECK-LABEL: strict_convert_signed: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: fcvtzs w0, d0 @@ -224,7 +224,7 @@ define i32 @strict_convert_signed(double %x) { ret i32 %cvt } -define i32 @strict_convert_unsigned(float %x) { +define i32 @strict_convert_unsigned(float %x) #0 { ; CHECK-LABEL: strict_convert_unsigned: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: fcvtzu w0, s0 diff --git a/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-int-to-fp.ll b/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-int-to-fp.ll index 83403fc4ad86f..9e96355fd598d 100644 --- a/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-int-to-fp.ll +++ b/llvm/test/CodeGen/AArch64/sve-streaming-mode-cvt-int-to-fp.ll @@ -209,7 +209,7 @@ entry: ret double %cvt } -define float @strict_convert_signed(i32 %x) { +define float @strict_convert_signed(i32 %x) #0 { ; CHECK-LABEL: strict_convert_signed: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: scvtf s0, w0 @@ -224,7 +224,7 @@ entry: ret float %cvt } -define float @strict_convert_unsigned(i64 %x) { +define float @strict_convert_unsigned(i64 %x) #0 { ; CHECK-LABEL: strict_convert_unsigned: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ucvtf s0, x0 diff --git a/llvm/test/CodeGen/PowerPC/milicode32.ll b/llvm/test/CodeGen/PowerPC/milicode32.ll index 2c7e5c9867137..f2caec7e0045f 100644 --- a/llvm/test/CodeGen/PowerPC/milicode32.ll +++ b/llvm/test/CodeGen/PowerPC/milicode32.ll @@ -68,7 +68,7 @@ entry: ret i32 %call } -define i32 @strlen_test_fp_strict(ptr noundef %str) nounwind { +define i32 @strlen_test_fp_strict(ptr noundef %str) strictfp nounwind { ; CHECK-AIX-32-P9-LABEL: strlen_test_fp_strict: ; CHECK-AIX-32-P9: # %bb.0: # %entry ; CHECK-AIX-32-P9-NEXT: mflr r0 diff --git a/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll b/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll index c1ee436a40c55..756cc6dc9408c 100644 --- a/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll +++ b/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll @@ -1972,14 +1972,12 @@ entry: ret ppc_fp128 %conv } -define i1 @ppcq_to_s1(ppc_fp128 %a) { +define i1 @ppcq_to_s1(ppc_fp128 %a) #0 { ; PC64LE-LABEL: ppcq_to_s1: ; PC64LE: # %bb.0: # %entry ; PC64LE-NEXT: mflr 0 ; PC64LE-NEXT: stdu 1, -32(1) ; PC64LE-NEXT: std 0, 48(1) -; PC64LE-NEXT: .cfi_def_cfa_offset 32 -; PC64LE-NEXT: .cfi_offset lr, 16 ; PC64LE-NEXT: bl __gcc_qtou ; PC64LE-NEXT: nop ; PC64LE-NEXT: addi 1, 1, 32 @@ -1992,8 +1990,6 @@ define i1 @ppcq_to_s1(ppc_fp128 %a) { ; PC64LE9-NEXT: mflr 0 ; PC64LE9-NEXT: stdu 1, -32(1) ; PC64LE9-NEXT: std 0, 48(1) -; PC64LE9-NEXT: .cfi_def_cfa_offset 32 -; PC64LE9-NEXT: .cfi_offset lr, 16 ; PC64LE9-NEXT: bl __gcc_qtou ; PC64LE9-NEXT: nop ; PC64LE9-NEXT: addi 1, 1, 32 @@ -2006,8 +2002,6 @@ define i1 @ppcq_to_s1(ppc_fp128 %a) { ; PC64-NEXT: mflr 0 ; PC64-NEXT: stdu 1, -112(1) ; PC64-NEXT: std 0, 128(1) -; PC64-NEXT: .cfi_def_cfa_offset 112 -; PC64-NEXT: .cfi_offset lr, 16 ; PC64-NEXT: bl __gcc_qtou ; PC64-NEXT: nop ; PC64-NEXT: addi 1, 1, 112 @@ -2019,14 +2013,12 @@ entry: ret i1 %conv } -define i1 @ppcq_to_u1(ppc_fp128 %a) { +define i1 @ppcq_to_u1(ppc_fp128 %a) #0 { ; PC64LE-LABEL: ppcq_to_u1: ; PC64LE: # %bb.0: # %entry ; PC64LE-NEXT: mflr 0 ; PC64LE-NEXT: stdu 1, -32(1) ; PC64LE-NEXT: std 0, 48(1) -; PC64LE-NEXT: .cfi_def_cfa_offset 32 -; PC64LE-NEXT: .cfi_offset lr, 16 ; PC64LE-NEXT: bl __fixunstfsi ; PC64LE-NEXT: nop ; PC64LE-NEXT: addi 1, 1, 32 @@ -2039,8 +2031,6 @@ define i1 @ppcq_to_u1(ppc_fp128 %a) { ; PC64LE9-NEXT: mflr 0 ; PC64LE9-NEXT: stdu 1, -32(1) ; PC64LE9-NEXT: std 0, 48(1) -; PC64LE9-NEXT: .cfi_def_cfa_offset 32 -; PC64LE9-NEXT: .cfi_offset lr, 16 ; PC64LE9-NEXT: bl __fixunstfsi ; PC64LE9-NEXT: nop ; PC64LE9-NEXT: addi 1, 1, 32 @@ -2053,8 +2043,6 @@ define i1 @ppcq_to_u1(ppc_fp128 %a) { ; PC64-NEXT: mflr 0 ; PC64-NEXT: stdu 1, -112(1) ; PC64-NEXT: std 0, 128(1) -; PC64-NEXT: .cfi_def_cfa_offset 112 -; PC64-NEXT: .cfi_offset lr, 16 ; PC64-NEXT: bl __fixunstfsi ; PC64-NEXT: nop ; PC64-NEXT: addi 1, 1, 112 diff --git a/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll index 53fcfa19725db..654d99948bd40 100644 --- a/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll @@ -1989,7 +1989,7 @@ define i64 @llround_f64(double %a) nounwind strictfp { ret i64 %1 } -define double @ldexp_f64(double %x, i32 signext %y) nounwind { +define double @ldexp_f64(double %x, i32 signext %y) nounwind strictfp { ; RV32IFD-LABEL: ldexp_f64: ; RV32IFD: # %bb.0: ; RV32IFD-NEXT: addi sp, sp, -16 diff --git a/llvm/test/CodeGen/RISCV/float-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/float-intrinsics-strict.ll index 3a4acfd8a41ee..b22661976e727 100644 --- a/llvm/test/CodeGen/RISCV/float-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/float-intrinsics-strict.ll @@ -1955,7 +1955,7 @@ define i64 @llround_f32(float %a) nounwind strictfp { ret i64 %1 } -define float @ldexp_f32(float %x, i32 signext %y) nounwind { +define float @ldexp_f32(float %x, i32 signext %y) nounwind strictfp { ; RV32IF-LABEL: ldexp_f32: ; RV32IF: # %bb.0: ; RV32IF-NEXT: addi sp, sp, -16 diff --git a/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll index eb1848965a9ba..c876b76b8f0d9 100644 --- a/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/zfh-half-intrinsics-strict.ll @@ -714,7 +714,7 @@ define i64 @llround_f16(half %a) nounwind strictfp { ret i64 %1 } -define half @ldexp_f16(half %x, i32 signext %y) nounwind { +define half @ldexp_f16(half %x, i32 signext %y) nounwind strictfp { ; RV32IZFH-LABEL: ldexp_f16: ; RV32IZFH: # %bb.0: ; RV32IZFH-NEXT: addi sp, sp, -16 diff --git a/llvm/test/CodeGen/RISCV/zfhmin-half-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/zfhmin-half-intrinsics-strict.ll index 0529819a4f4e2..891ffa0a0c96b 100644 --- a/llvm/test/CodeGen/RISCV/zfhmin-half-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/zfhmin-half-intrinsics-strict.ll @@ -744,7 +744,7 @@ define i64 @llround_f16(half %a) nounwind strictfp { ret i64 %1 } -define half @ldexp_f16(half %x, i32 signext %y) nounwind { +define half @ldexp_f16(half %x, i32 signext %y) nounwind strictfp { ; RV32IZFHMIN-LABEL: ldexp_f16: ; RV32IZFHMIN: # %bb.0: ; RV32IZFHMIN-NEXT: addi sp, sp, -16 diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll index b2d4f570afbd9..67eed241354d2 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-fmuladd.ll @@ -10,7 +10,7 @@ ; CHECK: OpFMul %[[#]] %[[#]] %[[#]] ; CHECK: OpFAdd %[[#]] %[[#]] %[[#]] -define spir_kernel void @test_f32(float %a) { +define spir_kernel void @test_f32(float %a) strictfp { entry: %r = tail call float @llvm.experimental.constrained.fmuladd.f32( float %a, float %a, float %a, @@ -18,9 +18,9 @@ entry: ret void } -; CHECK: OpFMul %[[#]] %[[#]] %[[#]] +; CHECK: OpFMul %[[#]] %[[#]] %[[#]] ; CHECK: OpFAdd %[[#]] %[[#]] %[[#]] -define spir_kernel void @test_f64(double %a) { +define spir_kernel void @test_f64(double %a) strictfp { entry: %r = tail call double @llvm.experimental.constrained.fmuladd.f64( double %a, double %a, double %a, @@ -30,7 +30,7 @@ entry: ; CHECK: OpFMul %[[#]] %[[#]] %[[#]] ; CHECK: OpFAdd %[[#]] %[[#]] %[[#]] -define spir_kernel void @test_v2f32(<2 x float> %a) { +define spir_kernel void @test_v2f32(<2 x float> %a) strictfp { entry: %r = tail call <2 x float> @llvm.experimental.constrained.fmuladd.v2f32( <2 x float> %a, <2 x float> %a, <2 x float> %a, @@ -40,7 +40,7 @@ entry: ; CHECK: OpFMul %[[#]] %[[#]] %[[#]] ; CHECK: OpFAdd %[[#]] %[[#]] %[[#]] -define spir_kernel void @test_v4f32(<4 x float> %a) { +define spir_kernel void @test_v4f32(<4 x float> %a) strictfp { entry: %r = tail call <4 x float> @llvm.experimental.constrained.fmuladd.v4f32( <4 x float> %a, <4 x float> %a, <4 x float> %a, @@ -50,7 +50,7 @@ entry: ; CHECK: OpFMul %[[#]] %[[#]] %[[#]] ; CHECK: OpFAdd %[[#]] %[[#]] %[[#]] -define spir_kernel void @test_v2f64(<2 x double> %a) { +define spir_kernel void @test_v2f64(<2 x double> %a) strictfp { entry: %r = tail call <2 x double> @llvm.experimental.constrained.fmuladd.v2f64( <2 x double> %a, <2 x double> %a, <2 x double> %a, diff --git a/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll index 1dbffd962a638..b8854e3061dbf 100644 --- a/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll +++ b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll @@ -13,7 +13,7 @@ declare i8 @buz.fp(float, float) define i8 @same_parent_combine_ diff _attrs(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2:[0-9]+]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -27,7 +27,7 @@ define i8 @same_parent_combine_ diff _attrs(i8 %x, i8 %y) { define i8 @same_parent_combine_ diff _attrs_needs_intersect(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_needs_intersect( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] +; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -41,7 +41,7 @@ define i8 @same_parent_combine_ diff _attrs_needs_intersect(i8 %x, i8 %y) { define i8 @same_parent_combine_ diff _attrs_fmf(float %x, float %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_fmf( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR3:[0-9]+]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C1]], float [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -55,7 +55,7 @@ define i8 @same_parent_combine_ diff _attrs_fmf(float %x, float %y) { define i8 @same_parent_combine_ diff _attrs_fmf2(float %x, float %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_fmf2( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR1]] +; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C1]], float [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -69,7 +69,7 @@ define i8 @same_parent_combine_ diff _attrs_fmf2(float %x, float %y) { define i8 @same_parent_combine_ diff _attrs_needs_intersect2(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_needs_intersect2( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR3]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -83,7 +83,7 @@ define i8 @same_parent_combine_ diff _attrs_needs_intersect2(i8 %x, i8 %y) { define i8 @same_parent_combine_ diff _attrs_really_needs_intersect(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_really_needs_intersect( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR3]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -112,7 +112,7 @@ define i8 @same_parent_combine_ diff _attrs_fail_side_effects(i8 %x, i8 %y) { define i8 @same_parent_combine_ diff _attrs_quasi_side_effects2(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_quasi_side_effects2( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]] +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] @@ -127,10 +127,10 @@ define i8 @same_parent_combine_ diff _attrs_quasi_side_effects2(i8 %x, i8 %y) { define i8 @ diff _parent_combine_ diff _attrs(i1 %c, i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @ diff _parent_combine_ diff _attrs( ; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]] ; CHECK: [[T]]: -; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR3]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; CHECK: [[F]]: @@ -151,7 +151,7 @@ F: define i8 @ diff _parent_combine_ diff _attrs_preserves_return_attrs(i1 %c, i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @ diff _parent_combine_ diff _attrs_preserves_return_attrs( ; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR3]] ; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]] ; CHECK: [[T]]: ; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]]) @@ -172,8 +172,8 @@ F: define i8 @same_parent_combine_ diff _attrs_todo(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_todo( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] -; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR4:[0-9]+]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -184,11 +184,12 @@ define i8 @same_parent_combine_ diff _attrs_todo(i8 %x, i8 %y) { } -define i8 @same_parent_combine_ diff _attrs_fail(i8 %x, i8 %y) { +define i8 @same_parent_combine_ diff _attrs_fail(i8 %x, i8 %y) strictfp { +; CHECK: Function Attrs: strictfp ; CHECK-LABEL: define i8 @same_parent_combine_ diff _attrs_fail( -; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] -; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR4:[0-9]+]] +; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] +; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR5:[0-9]+]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; @@ -202,10 +203,10 @@ define i8 @same_parent_combine_ diff _attrs_fail(i8 %x, i8 %y) { define i8 @ diff _parent_combine_ diff _attrs_todo(i1 %c, i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @ diff _parent_combine_ diff _attrs_todo( ; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]] ; CHECK: [[T]]: -; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR5:[0-9]+]] +; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR6:[0-9]+]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; CHECK: [[F]]: @@ -223,13 +224,14 @@ F: ret i8 %r2 } -define i8 @ diff _parent_combine_ diff _attrs_fail(i1 %c, i8 %x, i8 %y) { +define i8 @ diff _parent_combine_ diff _attrs_fail(i1 %c, i8 %x, i8 %y) strictfp { +; CHECK: Function Attrs: strictfp ; CHECK-LABEL: define i8 @ diff _parent_combine_ diff _attrs_fail( -; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { -; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]] +; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR2]] ; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]] ; CHECK: [[T]]: -; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR4]] +; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR5]] ; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]]) ; CHECK-NEXT: ret i8 [[R]] ; CHECK: [[F]]: @@ -247,10 +249,11 @@ F: ret i8 %r2 } -define i32 @commutative_intrinsic_intersection_failure(i32 %arg, i32 %arg1) { +define i32 @commutative_intrinsic_intersection_failure(i32 %arg, i32 %arg1) strictfp { +; CHECK: Function Attrs: strictfp ; CHECK-LABEL: define i32 @commutative_intrinsic_intersection_failure( -; CHECK-SAME: i32 [[ARG:%.*]], i32 [[ARG1:%.*]]) { -; CHECK-NEXT: [[CALL:%.*]] = call i32 @llvm.smin.i32(i32 [[ARG]], i32 [[ARG1]]) #[[ATTR6:[0-9]+]] +; CHECK-SAME: i32 [[ARG:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[CALL:%.*]] = call i32 @llvm.smin.i32(i32 [[ARG]], i32 [[ARG1]]) #[[ATTR0]] ; CHECK-NEXT: [[CALL2:%.*]] = call i32 @llvm.smin.i32(i32 [[ARG1]], i32 [[ARG]]) ; CHECK-NEXT: [[OR:%.*]] = or i32 [[CALL2]], [[CALL]] ; CHECK-NEXT: ret i32 [[OR]] @@ -262,11 +265,11 @@ define i32 @commutative_intrinsic_intersection_failure(i32 %arg, i32 %arg1) { } ;. -; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) } -; CHECK: attributes #[[ATTR1]] = { memory(none) } -; CHECK: attributes #[[ATTR2]] = { memory(read) } -; CHECK: attributes #[[ATTR3]] = { alwaysinline memory(none) } -; CHECK: attributes #[[ATTR4]] = { strictfp memory(none) } -; CHECK: attributes #[[ATTR5]] = { noinline optnone memory(none) } -; CHECK: attributes #[[ATTR6]] = { strictfp } +; CHECK: attributes #[[ATTR0]] = { strictfp } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) } +; CHECK: attributes #[[ATTR2]] = { memory(none) } +; CHECK: attributes #[[ATTR3]] = { memory(read) } +; CHECK: attributes #[[ATTR4]] = { alwaysinline memory(none) } +; CHECK: attributes #[[ATTR5]] = { strictfp memory(none) } +; CHECK: attributes #[[ATTR6]] = { noinline optnone memory(none) } ;. diff --git a/llvm/test/Transforms/InstCombine/erf.ll b/llvm/test/Transforms/InstCombine/erf.ll index 9f83acabb6fb7..57015fb490a7e 100644 --- a/llvm/test/Transforms/InstCombine/erf.ll +++ b/llvm/test/Transforms/InstCombine/erf.ll @@ -75,7 +75,7 @@ define double @erf_inf() { define float @erff_inf_memory_none() { ; CHECK-LABEL: define float @erff_inf_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call float @erff(float +inf) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: [[R:%.*]] = call float @erff(float +inf) #[[ATTR2:[0-9]+]] ; CHECK-NEXT: ret float [[R]] ; %r = call float @erff(float 0x7FF0000000000000) readnone @@ -84,7 +84,7 @@ define float @erff_inf_memory_none() { define double @erf_inf_memory_none() { ; CHECK-LABEL: define double @erf_inf_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call double @erf(double +inf) #[[ATTR1]] +; CHECK-NEXT: [[R:%.*]] = call double @erf(double +inf) #[[ATTR2]] ; CHECK-NEXT: ret double [[R]] ; %r = call double @erf(double 0x7FF0000000000000) readnone @@ -111,7 +111,7 @@ define double @erf_neg_inf() { define float @erff_neg_inf_memory_none() { ; CHECK-LABEL: define float @erff_neg_inf_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call float @erff(float -inf) #[[ATTR1]] +; CHECK-NEXT: [[R:%.*]] = call float @erff(float -inf) #[[ATTR2]] ; CHECK-NEXT: ret float [[R]] ; %r = call float @erff(float 0xFFF0000000000000) readnone @@ -120,7 +120,7 @@ define float @erff_neg_inf_memory_none() { define double @erf_neg_inf_memory_none() { ; CHECK-LABEL: define double @erf_neg_inf_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call double @erf(double -inf) #[[ATTR1]] +; CHECK-NEXT: [[R:%.*]] = call double @erf(double -inf) #[[ATTR2]] ; CHECK-NEXT: ret double [[R]] ; %r = call double @erf(double 0xFFF0000000000000) readnone @@ -147,7 +147,7 @@ define double @erf_nan() { define float @erff_nan_memory_none() { ; CHECK-LABEL: define float @erff_nan_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call float @erff(float +qnan) #[[ATTR1]] +; CHECK-NEXT: [[R:%.*]] = call float @erff(float +qnan) #[[ATTR2]] ; CHECK-NEXT: ret float [[R]] ; %r = call float @erff(float 0x7FF8000000000000) readnone @@ -156,7 +156,7 @@ define float @erff_nan_memory_none() { define double @erf_nan_memory_none() { ; CHECK-LABEL: define double @erf_nan_memory_none() { -; CHECK-NEXT: [[R:%.*]] = call double @erf(double +qnan) #[[ATTR1]] +; CHECK-NEXT: [[R:%.*]] = call double @erf(double +qnan) #[[ATTR2]] ; CHECK-NEXT: ret double [[R]] ; %r = call double @erf(double 0x7FF8000000000000) readnone @@ -181,36 +181,40 @@ define double @erf_poison() { ret double %r } -define float @erff_const_strictfp() { -; CHECK-LABEL: define float @erff_const_strictfp() { -; CHECK-NEXT: [[R:%.*]] = call float @erff(float 5.000000e-01) #[[ATTR2:[0-9]+]] +define float @erff_const_strictfp() strictfp { +; CHECK-LABEL: define float @erff_const_strictfp( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[R:%.*]] = call float @erff(float 5.000000e-01) #[[ATTR0]] ; CHECK-NEXT: ret float [[R]] ; %r = call float @erff(float 5.000000e-01) strictfp ret float %r } -define double @erf_const_strictfp() { -; CHECK-LABEL: define double @erf_const_strictfp() { -; CHECK-NEXT: [[R:%.*]] = call double @erf(double -5.000000e-01) #[[ATTR2]] +define double @erf_const_strictfp() strictfp { +; CHECK-LABEL: define double @erf_const_strictfp( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[R:%.*]] = call double @erf(double -5.000000e-01) #[[ATTR0]] ; CHECK-NEXT: ret double [[R]] ; %r = call double @erf(double -5.000000e-01) strictfp ret double %r } -define float @erff_nan_strictfp() { -; CHECK-LABEL: define float @erff_nan_strictfp() { -; CHECK-NEXT: [[R:%.*]] = call float @erff(float +qnan) #[[ATTR2]] +define float @erff_nan_strictfp() strictfp { +; CHECK-LABEL: define float @erff_nan_strictfp( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[R:%.*]] = call float @erff(float +qnan) #[[ATTR0]] ; CHECK-NEXT: ret float [[R]] ; %r = call float @erff(float 0x7FF8000000000000) strictfp ret float %r } -define double @erf_nan_strictfp() { -; CHECK-LABEL: define double @erf_nan_strictfp() { -; CHECK-NEXT: [[R:%.*]] = call double @erf(double +qnan) #[[ATTR2]] +define double @erf_nan_strictfp() strictfp { +; CHECK-LABEL: define double @erf_nan_strictfp( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[R:%.*]] = call double @erf(double +qnan) #[[ATTR0]] ; CHECK-NEXT: ret double [[R]] ; %r = call double @erf(double 0x7FF8000000000000) strictfp diff --git a/llvm/test/Transforms/InstCombine/fdim.ll b/llvm/test/Transforms/InstCombine/fdim.ll index edbdaedc975c0..f167a842642db 100644 --- a/llvm/test/Transforms/InstCombine/fdim.ll +++ b/llvm/test/Transforms/InstCombine/fdim.ll @@ -99,9 +99,10 @@ define double @fdim_nzero() { ret double %dim } -define double @fdim_strictfp() { -; CHECK-LABEL: define double @fdim_strictfp() { -; CHECK-NEXT: [[DIM:%.*]] = call double @fdim(double 1.000000e+01, double 8.000000e+00) #[[ATTR1:[0-9]+]] +define double @fdim_strictfp() strictfp { +; CHECK-LABEL: define double @fdim_strictfp( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[DIM:%.*]] = call double @fdim(double 1.000000e+01, double 8.000000e+00) #[[ATTR0]] ; CHECK-NEXT: ret double [[DIM]] ; %dim = call double @fdim(double 10.0, double 8.0) strictfp diff --git a/llvm/test/Transforms/InstSimplify/disable_folding.ll b/llvm/test/Transforms/InstSimplify/disable_folding.ll index 69892012629bc..02ec4877e51d9 100644 --- a/llvm/test/Transforms/InstSimplify/disable_folding.ll +++ b/llvm/test/Transforms/InstSimplify/disable_folding.ll @@ -31,9 +31,10 @@ define float @test_llvm_sin() { } ; Should not be folded, even when -disable-fp-call-folding is not set, as it is marked as strictfp. -define float @test_fmax_ftz_nan_f_strictfp() { -; CHECK-LABEL: define float @test_fmax_ftz_nan_f_strictfp() { -; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fmax.ftz.nan.f(float 1.250000e+00, float -2.000000e+00) #[[ATTR1:[0-9]+]] +define float @test_fmax_ftz_nan_f_strictfp() #1 { +; CHECK-LABEL: define float @test_fmax_ftz_nan_f_strictfp( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[RES:%.*]] = call float @llvm.nvvm.fmax.ftz.nan.f(float 1.250000e+00, float -2.000000e+00) #[[ATTR0]] ; CHECK-NEXT: ret float [[RES]] ; %res = call float @llvm.nvvm.fmax.ftz.nan.f(float 1.25, float -2.0) #1 @@ -42,9 +43,10 @@ define float @test_fmax_ftz_nan_f_strictfp() { ; Check that strictfp disables folding for LLVM math intrinsics like sin.f32 ; even when -disable-fp-call-folding is not set. -define float @test_llvm_sin_strictfp() { -; CHECK-LABEL: define float @test_llvm_sin_strictfp() { -; CHECK-NEXT: [[RES:%.*]] = call float @llvm.sin.f32(float 5.000000e-01) #[[ATTR1]] +define float @test_llvm_sin_strictfp() #1 { +; CHECK-LABEL: define float @test_llvm_sin_strictfp( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[RES:%.*]] = call float @llvm.sin.f32(float 5.000000e-01) #[[ATTR0]] ; CHECK-NEXT: ret float [[RES]] ; %res = call float @llvm.sin.f32(float 0.5) #1 diff --git a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll index 95114abb4ef5f..0479fdb183f4c 100644 --- a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll @@ -411,7 +411,7 @@ define void @t7_nomerge0() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN1]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1:[0-9]+]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2:[0-9]+]] ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]] ; CHECK: [[INVOKE_CONT2]]: ; CHECK-NEXT: unreachable @@ -454,7 +454,7 @@ define void @t8_nomerge1() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]] ; CHECK: [[IF_THEN0]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]] ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]] ; CHECK: [[INVOKE_CONT0]]: ; CHECK-NEXT: unreachable @@ -510,7 +510,7 @@ define void @t9_nomerge2() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]] ; CHECK: [[IF_THEN0]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]] ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]] ; CHECK: [[INVOKE_CONT0]]: ; CHECK-NEXT: unreachable @@ -523,7 +523,7 @@ define void @t9_nomerge2() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1:.*]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN1]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR1]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]] ; CHECK-NEXT: to label %[[INVOKE_CONT2:.*]] unwind label %[[LPAD]] ; CHECK: [[INVOKE_CONT2]]: ; CHECK-NEXT: unreachable @@ -1075,7 +1075,7 @@ define void @t17_mismatched_attrs_okay_merge_intersect() personality ptr @__gxx_ ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN1_INVOKE]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2:[0-9]+]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR3:[0-9]+]] ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]] ; CHECK: [[IF_THEN1_CONT]]: ; CHECK-NEXT: unreachable @@ -1127,7 +1127,7 @@ define void @t17_mismatched_attrs_okay_merge_intersect2() personality ptr @__gxx ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN1_INVOKE]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR3]] ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]] ; CHECK: [[IF_THEN1_CONT]]: ; CHECK-NEXT: unreachable @@ -1166,13 +1166,15 @@ if.end: } -define void @t17_mismatched_attrs_prevent_merge() personality ptr @__gxx_personality_v0 { -; CHECK-LABEL: define void @t17_mismatched_attrs_prevent_merge() personality ptr @__gxx_personality_v0 { +define void @t17_mismatched_attrs_prevent_merge() strictfp personality ptr @__gxx_personality_v0 { +; CHECK: Function Attrs: strictfp +; CHECK-LABEL: define void @t17_mismatched_attrs_prevent_merge( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C0]], label %[[IF_THEN0:.*]], label %[[IF_ELSE:.*]] ; CHECK: [[IF_THEN0]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR3:[0-9]+]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR0]] ; CHECK-NEXT: to label %[[INVOKE_CONT0:.*]] unwind label %[[LPAD:.*]] ; CHECK: [[INVOKE_CONT0]]: ; CHECK-NEXT: unreachable @@ -1239,7 +1241,7 @@ define void @t18_attributes_are_preserved() personality ptr @__gxx_personality_v ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN1_INVOKE]], label %[[IF_END:.*]] ; CHECK: [[IF_THEN1_INVOKE]]: -; CHECK-NEXT: invoke void @simple_throw() #[[ATTR2]] +; CHECK-NEXT: invoke void @simple_throw() #[[ATTR3]] ; CHECK-NEXT: to label %[[IF_THEN1_CONT:.*]] unwind label %[[LPAD]] ; CHECK: [[IF_THEN1_CONT]]: ; CHECK-NEXT: unreachable @@ -2675,8 +2677,8 @@ declare void @consume(i32) declare dso_local i32 @__gxx_personality_v0(...) ;. -; CHECK: attributes #[[ATTR0:[0-9]+]] = { noreturn } -; CHECK: attributes #[[ATTR1]] = { nomerge } -; CHECK: attributes #[[ATTR2]] = { memory(none) } -; CHECK: attributes #[[ATTR3]] = { strictfp } +; CHECK: attributes #[[ATTR0]] = { strictfp } +; CHECK: attributes #[[ATTR1:[0-9]+]] = { noreturn } +; CHECK: attributes #[[ATTR2]] = { nomerge } +; CHECK: attributes #[[ATTR3]] = { memory(none) } ;. diff --git a/llvm/unittests/IR/VerifierTest.cpp b/llvm/unittests/IR/VerifierTest.cpp index 48d461cab330a..f6a89cde0901b 100644 --- a/llvm/unittests/IR/VerifierTest.cpp +++ b/llvm/unittests/IR/VerifierTest.cpp @@ -699,4 +699,28 @@ TEST(VerifierTest, IntrinsicRetInvalidStruct) { } } +TEST(VerifierTest, InvalidStrictFPAttribute) { + LLVMContext Ctx; + Module M("M", Ctx); + FunctionType *FuncTy = + FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false); + Function *F = + Function::Create(FuncTy, Function::ExternalLinkage, "strictfp_test", M); + BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F); + Type *FloatTy = Type::getFloatTy(Ctx); + + Function *CosF = + Intrinsic::getOrInsertDeclaration(&M, Intrinsic::cos, FloatTy); + CallInst *CI = CallInst::Create(CosF, ConstantFP::getNullValue(FloatTy), + "strictfp_call", Entry); + CI->addFnAttr(Attribute::StrictFP); + ReturnInst::Create(Ctx, Entry); + + std::string Error; + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE(StringRef(Error).starts_with( + "call site marked strictfp without caller function marked strictfp")) + << Error; +} } // end anonymous namespace diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir index 6910a06992b55..7a362ebe2421e 100644 --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -596,9 +596,9 @@ llvm.func @masked_gather_scatter_intrinsics(%M: vector<7 x !llvm.ptr>, %mask: ve } // CHECK-LABEL: @masked_expand_compress_intrinsics -llvm.func @masked_expand_compress_intrinsics(%ptr: !llvm.ptr, %mask: vector<7xi1>, %passthru: vector<7xf32>) { +llvm.func @masked_expand_compress_intrinsics(%ptr: !llvm.ptr, %mask: vector<7xi1>, %passthrough: vector<7xf32>) { // CHECK: call <7 x float> @llvm.masked.expandload.v7f32.p0(ptr %{{.*}}, <7 x i1> %{{.*}}, <7 x float> %{{.*}}) - %0 = "llvm.intr.masked.expandload"(%ptr, %mask, %passthru) + %0 = "llvm.intr.masked.expandload"(%ptr, %mask, %passthrough) : (!llvm.ptr, vector<7xi1>, vector<7xf32>) -> (vector<7xf32>) // CHECK: call void @llvm.masked.compressstore.v7f32.p0(<7 x float> %{{.*}}, ptr %{{.*}}, <7 x i1> %{{.*}}) "llvm.intr.masked.compressstore"(%0, %ptr, %mask) @@ -607,9 +607,9 @@ llvm.func @masked_expand_compress_intrinsics(%ptr: !llvm.ptr, %mask: vector<7xi1 } // CHECK-LABEL: @masked_expand_compress_intrinsics_with_alignment -llvm.func @masked_expand_compress_intrinsics_with_alignment(%ptr: !llvm.ptr, %mask: vector<7xi1>, %passthru: vector<7xf32>) { +llvm.func @masked_expand_compress_intrinsics_with_alignment(%ptr: !llvm.ptr, %mask: vector<7xi1>, %passthrough: vector<7xf32>) { // CHECK: call <7 x float> @llvm.masked.expandload.v7f32.p0(ptr align 8 %{{.*}}, <7 x i1> %{{.*}}, <7 x float> %{{.*}}) - %0 = "llvm.intr.masked.expandload"(%ptr, %mask, %passthru) {arg_attrs = [{llvm.align = 8 : i32}, {}, {}]} + %0 = "llvm.intr.masked.expandload"(%ptr, %mask, %passthrough) {arg_attrs = [{llvm.align = 8 : i32}, {}, {}]} : (!llvm.ptr, vector<7xi1>, vector<7xf32>) -> (vector<7xf32>) // CHECK: call void @llvm.masked.compressstore.v7f32.p0(<7 x float> %{{.*}}, ptr align 8 %{{.*}}, <7 x i1> %{{.*}}) "llvm.intr.masked.compressstore"(%0, %ptr, %mask) {arg_attrs = [{}, {llvm.align = 8 : i32}, {}]} @@ -1202,7 +1202,7 @@ llvm.func @vector_ptrmask(%p: vector<8 x !llvm.ptr>, %mask: vector<8 x i64>) -> } // CHECK-LABEL: @experimental_constrained_fadd -llvm.func @experimental_constrained_fadd(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fadd(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fadd.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1215,7 +1215,7 @@ llvm.func @experimental_constrained_fadd(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_fsub -llvm.func @experimental_constrained_fsub(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fsub(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fsub.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1228,7 +1228,7 @@ llvm.func @experimental_constrained_fsub(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_fmul -llvm.func @experimental_constrained_fmul(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fmul(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fmul.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1241,7 +1241,7 @@ llvm.func @experimental_constrained_fmul(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_fdiv -llvm.func @experimental_constrained_fdiv(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fdiv(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fdiv.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1254,7 +1254,7 @@ llvm.func @experimental_constrained_fdiv(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_frem -llvm.func @experimental_constrained_frem(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_frem(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.frem.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1267,7 +1267,7 @@ llvm.func @experimental_constrained_frem(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_fma -llvm.func @experimental_constrained_fma(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fma(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fma.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1280,7 +1280,7 @@ llvm.func @experimental_constrained_fma(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_fmuladd -llvm.func @experimental_constrained_fmuladd(%s: f32, %v: vector<4 x f32>) { +llvm.func @experimental_constrained_fmuladd(%s: f32, %v: vector<4 x f32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fmuladd.f32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1293,7 +1293,7 @@ llvm.func @experimental_constrained_fmuladd(%s: f32, %v: vector<4 x f32>) { } // CHECK-LABEL: @experimental_constrained_uitofp -llvm.func @experimental_constrained_uitofp(%s: i32, %v: vector<4 x i32>) { +llvm.func @experimental_constrained_uitofp(%s: i32, %v: vector<4 x i32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.uitofp.f32.i32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1322,7 +1322,7 @@ llvm.func @experimental_constrained_uitofp(%s: i32, %v: vector<4 x i32>) { } // CHECK-LABEL: @experimental_constrained_sitofp -llvm.func @experimental_constrained_sitofp(%s: i32, %v: vector<4 x i32>) { +llvm.func @experimental_constrained_sitofp(%s: i32, %v: vector<4 x i32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.sitofp.f32.i32( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1351,7 +1351,7 @@ llvm.func @experimental_constrained_sitofp(%s: i32, %v: vector<4 x i32>) { } // CHECK-LABEL: @experimental_constrained_fptrunc -llvm.func @experimental_constrained_fptrunc(%s: f64, %v: vector<4xf32>) { +llvm.func @experimental_constrained_fptrunc(%s: f64, %v: vector<4xf32>) attributes { passthrough = ["strictfp"] } { // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( // CHECK: metadata !"round.towardzero" // CHECK: metadata !"fpexcept.ignore" @@ -1380,7 +1380,7 @@ llvm.func @experimental_constrained_fptrunc(%s: f64, %v: vector<4xf32>) { } // CHECK-LABEL: @experimental_constrained_fpext -llvm.func @experimental_constrained_fpext(%s: f32, %v: vector<4xf32>) { +llvm.func @experimental_constrained_fpext(%s: f32, %v: vector<4xf32>) attributes { passthrough = ["strictfp"] } { // CHECK: call double @llvm.experimental.constrained.fpext.f64.f32( // CHECK: metadata !"fpexcept.ignore" %0 = llvm.intr.experimental.constrained.fpext %s ignore : f32 to f64 @@ -1426,13 +1426,13 @@ llvm.func @vector_scmp(%a: vector<4 x i32>, %b: vector<4 x i32>) -> vector<4 x i // Check that intrinsics are declared with appropriate types. // CHECK-DAG: declare float @llvm.fma.f32(float, float, float) -// CHECK-DAG: declare <8 x float> @llvm.fma.v8f32(<8 x float>, <8 x float>, <8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.fma.v8f32(<8 x float>, <8 x float>, <8 x float>) // CHECK-DAG: declare float @llvm.fmuladd.f32(float, float, float) -// CHECK-DAG: declare <8 x float> @llvm.fmuladd.v8f32(<8 x float>, <8 x float>, <8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.fmuladd.v8f32(<8 x float>, <8 x float>, <8 x float>) // CHECK-DAG: declare void @llvm.prefetch.p0(ptr readonly captures(none), i32 immarg range(i32 0, 2), i32 immarg range(i32 0, 4), i32 immarg range(i32 0, 2)) // CHECK-DAG: declare i1 @llvm.is.fpclass.f32(float, i32 immarg) // CHECK-DAG: declare float @llvm.exp.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.exp.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.exp.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.exp2.f32(float) // CHECK-DAG: declare <8 x float> @llvm.exp2.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.exp10.f32(float) @@ -1442,19 +1442,19 @@ llvm.func @vector_scmp(%a: vector<4 x i32>, %b: vector<4 x i32>) -> vector<4 x i // CHECK-DAG: declare { float, i32 } @llvm.frexp.f32.i32(float) // CHECK-DAG: declare { <8 x float>, i32 } @llvm.frexp.v8f32.i32(<8 x float>) // CHECK-DAG: declare float @llvm.log.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.log.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.log.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.log10.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.log10.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.log10.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.log2.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.log2.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.log2.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.fabs.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.fabs.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.fabs.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.sqrt.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.sqrt.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.sqrt.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.ceil.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.ceil.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.ceil.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.cos.f32(float) -// CHECK-DAG: declare <8 x float> @llvm.cos.v8f32(<8 x float>) #0 +// CHECK-DAG: declare <8 x float> @llvm.cos.v8f32(<8 x float>) // CHECK-DAG: declare { float, float } @llvm.sincos.f32(float) // CHECK-DAG: declare { <8 x float>, <8 x float> } @llvm.sincos.v8f32(<8 x float>) // CHECK-DAG: declare float @llvm.copysign.f32(float, float) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
