Skip to content

Commit b6b7341

Browse files
committed
[IR] Add FPOperation intrinsic property
The previous implementation of constrained functions passed floating-point parameters as metadata function arguments. They represented a part of the function signature and were mandatory. Passing such parameters to irrelevant functions were not possible. The new implementation passes the floating-point parameters in operand bundles. This is an optional call component and technically such bundles can be attached to any call. To keep IR cleaner, some mechanism is required to avoid setting FP bundles on irrelevant functions. This change implements such mechanism by introducing a new function attribute, "fpoperation". It should be set for built-in functions that operate floating-point values in some way and thus the parameters, represented by FP bundles, make sense for them. Verifier can check if FP bundles are attached to call to such functions only.
1 parent 8e64ef3 commit b6b7341

25 files changed

+78
-27
lines changed

clang/test/CodeGen/builtin-sqrt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ float foo(float X) {
1111
// HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} memory(none)
1212

1313
// NO_ERRNO: declare float @llvm.sqrt.f32(float) [[ATTR:#[0-9]+]]
14-
// NO_ERRNO: attributes [[ATTR]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
14+
// NO_ERRNO: attributes [[ATTR]] = { fpoperation nocallback nofree nosync nounwind speculatable willreturn memory(none) }
1515

clang/test/CodeGen/libcalls.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,4 @@ void test_builtins(double d, float f, long double ld) {
124124
}
125125

126126
// CHECK-YES: attributes [[NUW]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+x87" }
127-
// CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
127+
// CHECK-NO-DAG: attributes [[NUW_RNI]] = { fpoperation nocallback nofree nosync nounwind speculatable willreturn memory(none) }

clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ kernel void device_side_enqueue(global float *a, global float *b, int i) {
165165
// SPIR32: attributes #[[ATTR0]] = { convergent noinline norecurse nounwind optnone "denormal-fp-math-f32"="preserve-sign,preserve-sign" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" }
166166
// SPIR32: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
167167
// SPIR32: attributes #[[ATTR2]] = { convergent noinline nounwind optnone "denormal-fp-math-f32"="preserve-sign,preserve-sign" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
168-
// SPIR32: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
168+
// SPIR32: attributes #[[ATTR3:[0-9]+]] = { fpoperation nocallback nofree nosync nounwind speculatable willreturn memory(none) }
169169
// SPIR32: attributes #[[ATTR4]] = { convergent nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
170170
//.
171171
// STRICTFP: attributes #[[ATTR0]] = { convergent noinline norecurse nounwind optnone strictfp "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" }

llvm/docs/LangRef.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,6 +1964,9 @@ For example:
19641964
This attribute tells the code generator that returns from functions should
19651965
be replaced with jumps to externally-defined architecture-specific symbols.
19661966
For X86, this symbol's identifier is ``__x86_return_thunk``.
1967+
``fpoperation``
1968+
This attribute applies to built-in functions. It indicates that the function
1969+
may have :ref:`floating-point operand bundles <ob_fpe>`.
19671970
``"frame-pointer"``
19681971
This attribute tells the code generator whether the function
19691972
should keep the frame pointer. The code generator may emit the frame pointer

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ enum AttributeKindCodes {
787787
ATTR_KIND_CORO_ELIDE_SAFE = 98,
788788
ATTR_KIND_NO_EXT = 99,
789789
ATTR_KIND_NO_DIVERGENCE_SOURCE = 100,
790+
ATTR_KIND_FPOPERATION = 101,
790791
};
791792

792793
enum ComdatSelectionKindCodes {

llvm/include/llvm/IR/Attributes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ def StackProtectStrong : EnumAttr<"sspstrong", IntersectPreserve, [FnAttr]>;
308308
/// Function was called in a scope requiring strict floating point semantics.
309309
def StrictFP : EnumAttr<"strictfp", IntersectPreserve, [FnAttr]>;
310310

311+
/// Function is a floating point operation.
312+
def FPOperation : EnumAttr<"fpoperation", IntersectPreserve, [FnAttr]>;
313+
311314
/// Hidden pointer to structure to return.
312315
def StructRet : TypeAttr<"sret", IntersectPreserve, [ParamAttr]>;
313316

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ def IntrSpeculatable : IntrinsicProperty;
178178
// defined by the hasSideEffects property of the TableGen Instruction class.
179179
def IntrHasSideEffects : IntrinsicProperty;
180180

181+
/// This property indicates that the intrinsic represents a floating-point
182+
/// operation, and it may have floating-point operand bundles.
183+
def IntrFPOperation : IntrinsicProperty;
184+
181185
//===----------------------------------------------------------------------===//
182186
// IIT constants and utils
183187
//===----------------------------------------------------------------------===//
@@ -1020,7 +1024,7 @@ def int_experimental_memset_pattern
10201024
// FIXME: Add version of these floating point intrinsics which allow non-default
10211025
// rounding modes and FP exception handling.
10221026

1023-
let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
1027+
let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn, IntrFPOperation] in {
10241028
def int_fma : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10251029
[LLVMMatchType<0>, LLVMMatchType<0>,
10261030
LLVMMatchType<0>]>;
@@ -1089,27 +1093,27 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrWillReturn] in {
10891093

10901094
def int_minnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10911095
[LLVMMatchType<0>, LLVMMatchType<0>],
1092-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1096+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
10931097
>;
10941098
def int_maxnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10951099
[LLVMMatchType<0>, LLVMMatchType<0>],
1096-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1100+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
10971101
>;
10981102
def int_minimum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
10991103
[LLVMMatchType<0>, LLVMMatchType<0>],
1100-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1104+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
11011105
>;
11021106
def int_maximum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
11031107
[LLVMMatchType<0>, LLVMMatchType<0>],
1104-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1108+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
11051109
>;
11061110
def int_minimumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
11071111
[LLVMMatchType<0>, LLVMMatchType<0>],
1108-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1112+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
11091113
>;
11101114
def int_maximumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
11111115
[LLVMMatchType<0>, LLVMMatchType<0>],
1112-
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
1116+
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative, IntrFPOperation]
11131117
>;
11141118

11151119
// Internal interface for object size checking

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
20762076
return Attribute::ElementType;
20772077
case bitc::ATTR_KIND_FNRETTHUNK_EXTERN:
20782078
return Attribute::FnRetThunkExtern;
2079+
case bitc::ATTR_KIND_FPOPERATION:
2080+
return Attribute::FPOperation;
20792081
case bitc::ATTR_KIND_INLINE_HINT:
20802082
return Attribute::InlineHint;
20812083
case bitc::ATTR_KIND_IN_REG:

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
733733
return bitc::ATTR_KIND_DISABLE_SANITIZER_INSTRUMENTATION;
734734
case Attribute::FnRetThunkExtern:
735735
return bitc::ATTR_KIND_FNRETTHUNK_EXTERN;
736+
case Attribute::FPOperation:
737+
return bitc::ATTR_KIND_FPOPERATION;
736738
case Attribute::Hot:
737739
return bitc::ATTR_KIND_HOT;
738740
case Attribute::ElementType:

llvm/lib/IR/Verifier.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,6 +3799,10 @@ void Verifier::visitCallBase(CallBase &Call) {
37993799
"Value of fpe.round bundle operand is not a correct rounding mode",
38003800
Call);
38013801
FoundFpeRoundBundle = true;
3802+
Check(!Callee || isa<ConstrainedFPIntrinsic>(Call) ||
3803+
Callee->hasFnAttribute(Attribute::FPOperation) ||
3804+
!Callee->isIntrinsic(),
3805+
"This function call may not have fpe.control bundle", Call);
38023806
} else if (Tag == LLVMContext::OB_fpe_except) {
38033807
Check(!FoundFpeExceptBundle, "Multiple fpe.except operand bundles", Call);
38043808
Check(BU.Inputs.size() == 1,
@@ -3813,6 +3817,10 @@ void Verifier::visitCallBase(CallBase &Call) {
38133817
"behavior",
38143818
Call);
38153819
FoundFpeExceptBundle = true;
3820+
Check(!Callee || isa<ConstrainedFPIntrinsic>(Call) ||
3821+
Callee->hasFnAttribute(Attribute::FPOperation) ||
3822+
!Callee->isIntrinsic(),
3823+
"This function call may not have fpe.except bundle", Call);
38163824
}
38173825
}
38183826

0 commit comments

Comments
 (0)