-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[IR] Add new function attribute nocreateundeforpoison #164809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
ac95b57
40a3c93
bf32374
8652177
ab58489
5657809
2477738
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -186,6 +186,10 @@ def IntrSpeculatable : IntrinsicProperty; | |
| // defined by the hasSideEffects property of the TableGen Instruction class. | ||
| def IntrHasSideEffects : IntrinsicProperty; | ||
|
|
||
| // Result will not be undef or poison if all arguments are not undef and not | ||
| // poison. | ||
| def IntrNoCreateUndefOrPoison : IntrinsicProperty; | ||
|
|
||
| //===----------------------------------------------------------------------===// | ||
| // IIT constants and utils | ||
| //===----------------------------------------------------------------------===// | ||
|
|
@@ -1039,7 +1043,7 @@ def int_experimental_memset_pattern | |
| // FIXME: Add version of these floating point intrinsics which allow non-default | ||
| // rounding modes and FP exception handling. | ||
|
|
||
| let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { | ||
| def int_fma : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>, | ||
| LLVMMatchType<0>]>; | ||
|
|
@@ -1052,16 +1056,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | |
| // environment so they can be treated as readnone. | ||
| def int_sqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_powi : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>; | ||
| def int_asin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_acos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_atan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_atan2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; | ||
| def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_sinh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_cosh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>]>; | ||
| def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
|
|
@@ -1080,12 +1076,6 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | |
| def int_nearbyint : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_round : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_roundeven : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_sincos : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
| def int_sincospi : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
| def int_modf : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
|
|
||
| // Truncate a floating point number with a specific rounding mode | ||
| def int_fptrunc_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], | ||
|
|
@@ -1097,6 +1087,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | |
| def int_arithmetic_fence : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], | ||
| [IntrNoMem]>; | ||
|
|
||
| // If the value doesn't fit an unspecified value is returned, but this | ||
| // is not poison so we can still mark these as IntrNoCreateUndefOrPoison. | ||
| def int_lround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; | ||
| def int_llround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; | ||
| def int_lrint : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; | ||
|
|
@@ -1110,29 +1102,50 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | |
| def int_frexp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty, llvm_anyint_ty], [LLVMMatchType<0>]>; | ||
| } | ||
|
|
||
| // TODO: Move all of these into the IntrNoCreateUndefOrPoison case above. | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | ||
| // These functions do not read memory, but are sensitive to the | ||
| // rounding mode. LLVM purposely does not model changes to the FP | ||
| // environment so they can be treated as readnone. | ||
| def int_asin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a TODO to move these into the IntrNoCreateUndefOrPoison case above? I don't think any of these produce poison, they were just missing from the switch...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| def int_acos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_atan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_atan2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; | ||
| def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_sinh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_cosh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; | ||
| def int_sincos : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
| def int_sincospi : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
| def int_modf : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [llvm_anyfloat_ty]>; | ||
| } | ||
|
|
||
| def int_minnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
| def int_maxnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
| def int_minimum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
| def int_maximum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
| def int_minimumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
| def int_maximumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative] | ||
| [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] | ||
| >; | ||
|
|
||
| // Internal interface for object size checking | ||
|
|
@@ -1164,7 +1177,7 @@ let IntrProperties = [IntrInaccessibleMemOnly] in { | |
| def int_is_fpclass | ||
| : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], | ||
| [llvm_anyfloat_ty, llvm_i32_ty], | ||
| [IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<1>>]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, ImmArg<ArgIndex<1>>]>; | ||
|
|
||
| //===--------------- Constrained Floating Point Intrinsics ----------------===// | ||
| // | ||
|
|
@@ -1406,7 +1419,7 @@ def int_expect_with_probability : DefaultAttrsIntrinsic<[llvm_anyint_ty], | |
| // | ||
|
|
||
| // None of these intrinsics accesses memory at all. | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { | ||
| def int_bswap: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; | ||
| def int_ctpop: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; | ||
| def int_bitreverse : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; | ||
|
|
@@ -1522,7 +1535,7 @@ def int_adjust_trampoline : DefaultAttrsIntrinsic< | |
| // | ||
|
|
||
| // Expose the carry flag from add operations on two integrals. | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { | ||
| def int_sadd_with_overflow : DefaultAttrsIntrinsic<[llvm_anyint_ty, | ||
| LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>]>; | ||
|
|
@@ -1548,16 +1561,16 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | |
| // | ||
| def int_sadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Commutative]>; | ||
| def int_uadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable, Commutative]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Commutative]>; | ||
| def int_ssub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_usub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_sshl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], | ||
| [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
|
|
@@ -1612,22 +1625,22 @@ def int_abs : DefaultAttrsIntrinsic< | |
|
|
||
| def int_smax : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_smin : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_umax : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_umin : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
| def int_scmp : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], | ||
| [IntrNoMem, IntrSpeculatable, Range<RetIndex, -1, 2>]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Range<RetIndex, -1, 2>]>; | ||
| def int_ucmp : DefaultAttrsIntrinsic< | ||
| [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], | ||
| [IntrNoMem, IntrSpeculatable, Range<RetIndex, -1, 2>]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Range<RetIndex, -1, 2>]>; | ||
|
|
||
| //===------------------------- Memory Use Markers -------------------------===// | ||
| // | ||
|
|
@@ -1869,7 +1882,7 @@ def int_convert_from_fp16 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [llvm_i16_ | |
| } | ||
|
|
||
| // Saturating floating point to integer intrinsics | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable] in { | ||
| let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { | ||
| def int_fptoui_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; | ||
| def int_fptosi_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; | ||
| } | ||
|
|
@@ -1892,7 +1905,7 @@ def int_fake_use : DefaultAttrsIntrinsic<[], [llvm_vararg_ty], | |
| // First argument must be pointer or vector of pointer. This is checked by the | ||
| // verifier. | ||
| def int_ptrmask: DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, llvm_anyint_ty], | ||
| [IntrNoMem, IntrSpeculatable]>; | ||
| [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; | ||
|
|
||
| // Intrinsic to wrap a thread local variable. | ||
| def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to clarify the interaction with fast math flags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'm not sure exactly how to word it. How about:
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, something like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But same applies for other poison-generating metadata and attributes like
rangeand!rangeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the interaction with other attributes: I do not want to come up with an order of precedence of attributes, saying which ones take priority over other ones, and I do not think it is necessary. The way I understand it is there are a bunch of reasons why a call might return poison, including:
rangeattribute on the return value, and returning a value outside that rangenocreateundeforpoisonattributeI'm not sure how to explain this succinctly in the LangRef. Maybe I need to invert the description:
Does that help?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think phrasing it in terms of what it doesn't mean is worse. Can we phrase it in terms of... base value behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean by "base value" and I don't see that term used elsewhere. Are you suggesting we separate out the callee's internal view of the return value and the caller's external view of it? (Like "intensional" and "extensional" definitions in logic/semantics.)
nocreateundeforpoisonsays something about the internal view. Poison-generating attributes and fast math flags only affect the external view, e.g.nnansays that if the internal is NaN then the external is poison.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think something like this would be fine? "This attribute indicates that the result of the function (prior to application of return attributes/metadata) will not be undef or poison if all arguments are not undef and not poison."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I used that.