This is an archive of the discontinued LLVM Phabricator instance.

InstCombine: Fold cos(-x) -> cos(x)
ClosedPublic

Authored by arsenm on Jan 3 2017, 8:39 AM.

Details

Reviewers
davide

Diff Detail

Event Timeline

arsenm updated this revision to Diff 82894.Jan 3 2017, 8:39 AM
arsenm retitled this revision from to InstCombine: Fold cos(-x) -> cos(x).
arsenm updated this object.
arsenm added a subscriber: llvm-commits.
davide added a subscriber: davide.Jan 3 2017, 8:56 AM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

arsenm added a comment.Jan 3 2017, 9:04 AM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

This is not the case, it is supposed to behave exactly as the libcall: http://llvm.org/docs/LangRef.html#id439

davide added a comment.Jan 3 2017, 9:13 AM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

arsenm added a comment.Jan 3 2017, 1:54 PM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

The C standard is uselessly underspecified. It doesn't have any constraints on the precision of math functions. IMO having the intrinsic be the same as the libcall is not useful. e.g. errno is not a meaningful concept on all platforms, and the intent of intrinsics is usually to map to a machine instruction.

davide added a comment.Jan 3 2017, 3:05 PM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

The C standard is uselessly underspecified. It doesn't have any constraints on the precision of math functions. IMO having the intrinsic be the same as the libcall is not useful. e.g. errno is not a meaningful concept on all platforms, and the intent of intrinsics is usually to map to a machine instruction.

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

The C standard is uselessly underspecified. It doesn't have any constraints on the precision of math functions. IMO having the intrinsic be the same as the libcall is not useful. e.g. errno is not a meaningful concept on all platforms, and the intent of intrinsics is usually to map to a machine instruction.

I don't necessarily disagree, but I think that changing the semantic of cos would require a much wider discussion on llvm-dev.

arsenm added a comment.Jan 4 2017, 9:08 AM

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

The C standard is uselessly underspecified. It doesn't have any constraints on the precision of math functions. IMO having the intrinsic be the same as the libcall is not useful. e.g. errno is not a meaningful concept on all platforms, and the intent of intrinsics is usually to map to a machine instruction.

SimplifyLibCalls.cpp does a similar transformation (cos(-x) -> cos(x)).
I think we should have the logic for this simplifications in a single place, if possible, so maybe there we should unconditionally lower libc cos() -> llvm.cos and simplify here?

I think that needs to be part of a larger change to fix the mess of math intrinsic and libcall handling. In the case of cos, I view the cos function as somewhat different from llvm.cos. I expect the intrinsic to be a possibly less precise machine instruction version of cos rather than a fully correct library call so I'm not sure it should always be replaced with the intrinsic.

Not quite, as that would violate LangRef cos semantic. http://llvm.org/docs/LangRef.html#llvm-cos-intrinsic

The C standard is uselessly underspecified. It doesn't have any constraints on the precision of math functions. IMO having the intrinsic be the same as the libcall is not useful. e.g. errno is not a meaningful concept on all platforms, and the intent of intrinsics is usually to map to a machine instruction.

I don't necessarily disagree, but I think that changing the semantic of cos would require a much wider discussion on llvm-dev.

Getting back on topic, is there any objection to doing this optimization for the intrinsic (and for llvm.amdgcn.cos) separately here?

davide added a comment.Jan 4 2017, 9:19 AM

Getting back on topic, is there any objection to doing this optimization for the intrinsic (and for llvm.amdgcn.cos) separately here?

I think this is fine but if we go this route the code in SimplifyLibCalls should be removed and we should always lower there to @llvm.cos (as we do already for other intrinsics, FWIW, e.g. @llvm.fls)

davide added inline comments.Jan 4 2017, 9:22 AM
lib/Transforms/InstCombine/InstCombineCalls.cpp
1641

While here, I also noticed the amdgcn_cos is not documented in LangRef, maybe it could be (or somewhere else)

arsenm added inline comments.Jan 4 2017, 9:27 AM
lib/Transforms/InstCombine/InstCombineCalls.cpp
1641

Do we have formal documentation for target specific intrinsics? I thought only generic intrinsics belonged in the LangRef

davide requested changes to this revision.Jan 4 2017, 9:35 AM
davide added a reviewer: davide.
davide added inline comments.
lib/Transforms/InstCombine/InstCombineCalls.cpp
1643–1649

Please match against fabs as well here and update the tests.

This revision now requires changes to proceed.Jan 4 2017, 9:35 AM
arsenm updated this revision to Diff 83070.Jan 4 2017, 9:57 AM
arsenm edited edge metadata.

Also handle fabs.

davide accepted this revision.Jan 4 2017, 10:04 AM
davide edited edge metadata.

LGTM.

This revision is now accepted and ready to land.Jan 4 2017, 10:04 AM
arsenm closed this revision.Jan 4 2017, 3:00 PM

r291022