Will a C/C++ compiler optimise code by reusing a recently calculated function result?Writing Universal memoization function in C++11Can a compiler automatically detect pure functions without the type information about purity?__attribute__((const)) vs __attribute__((pure)) in GNU CFastest way to determine if an integer's square root is an integerWhy does C++ compilation take so long?How can I profile C++ code running on Linux?C++ code file extension? .cc vs .cppWhy do we need virtual functions in C++?Why is this program erroneously rejected by three C++ compilers?Can code that is valid in both C and C++ produce different behavior when compiled in each language?Swift compiler recursive code optimisations (similar to Haskell)C++ code for testing the Collatz conjecture faster than hand-written assembly - why?C++ sqrt function returning truncated (wrong) output
Are there types of animals that can't make the trip to space? (physiologically)
How do we know Nemesis is not a black hole (or neutron star)?
Why the first octet of a MAC address always end with a binary 0?
Writing about real people - not giving offence
Sending mail to the Professor for PhD, after seeing his tweet
Quote to show students don't have to fear making mistakes
What is the point of impeaching Trump?
GPLv3 forces us to make code available, but to who?
Is there a way to replace Smite with Sharpness on a weapon?
Is "Ram married his daughter" ambiguous?
Notation clarity question for a conglomerate of accidentals
Airport Security - advanced check, 4th amendment breach
IEEE 754 square root with Newton-Raphson
Can I bring this power bank on board the aircraft?
What's the correct way to determine turn order in this situation?
Do jackscrews suffer from blowdown?
Does the 'java' command compile Java programs?
Parent asking for money after I moved out
How to say "respectively" in German when listing (enumerating) things
Is there a pattern for handling conflicting function parameters?
Is spot metering just an EV compensation?
Should I be an author on another PhD student's paper if I went to their meetings and gave advice?
How do French and other Romance language speakers cope with the movable do system?
Why do Russians sometimes spell "жирный" (fatty) as "жырный"?
Will a C/C++ compiler optimise code by reusing a recently calculated function result?
Writing Universal memoization function in C++11Can a compiler automatically detect pure functions without the type information about purity?__attribute__((const)) vs __attribute__((pure)) in GNU CFastest way to determine if an integer's square root is an integerWhy does C++ compilation take so long?How can I profile C++ code running on Linux?C++ code file extension? .cc vs .cppWhy do we need virtual functions in C++?Why is this program erroneously rejected by three C++ compilers?Can code that is valid in both C and C++ produce different behavior when compiled in each language?Swift compiler recursive code optimisations (similar to Haskell)C++ code for testing the Collatz conjecture faster than hand-written assembly - why?C++ sqrt function returning truncated (wrong) output
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
Suppose I have a function double F(double x)
and let's assume for the sake of this example that calls to F
are costly.
Suppose I write a function f
that calculates the square root of F
:
double f(double x)
return sqrt(F(x));
and in a third function sum
I calculate the sum of f
and F
:
double sum(double x)
return F(x) + f(x);
Since I want to minimise calls to F
the above code is inefficient compared to e.g.
double sum_2(double x)
double y = F(x);
return y + sqrt(y);
But since I am lazy, or stupid, or want to make my code as clear as possible, I opted for the first definition instead.
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x)
can be reused to calculate f(x)
, as it is done in sum_2
?
Many thanks.
c++ c optimization compiler-optimization
|
show 1 more comment
Suppose I have a function double F(double x)
and let's assume for the sake of this example that calls to F
are costly.
Suppose I write a function f
that calculates the square root of F
:
double f(double x)
return sqrt(F(x));
and in a third function sum
I calculate the sum of f
and F
:
double sum(double x)
return F(x) + f(x);
Since I want to minimise calls to F
the above code is inefficient compared to e.g.
double sum_2(double x)
double y = F(x);
return y + sqrt(y);
But since I am lazy, or stupid, or want to make my code as clear as possible, I opted for the first definition instead.
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x)
can be reused to calculate f(x)
, as it is done in sum_2
?
Many thanks.
c++ c optimization compiler-optimization
1
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
I'm not an expert on such things, but it seems to me it may depend on howF()
is defined. Does it have side effects? Can it be inlined?
– Fred Larson
Mar 28 at 21:18
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows thatF
is called two times anyway.
– ForceBru
Mar 28 at 21:20
5
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
4
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26
|
show 1 more comment
Suppose I have a function double F(double x)
and let's assume for the sake of this example that calls to F
are costly.
Suppose I write a function f
that calculates the square root of F
:
double f(double x)
return sqrt(F(x));
and in a third function sum
I calculate the sum of f
and F
:
double sum(double x)
return F(x) + f(x);
Since I want to minimise calls to F
the above code is inefficient compared to e.g.
double sum_2(double x)
double y = F(x);
return y + sqrt(y);
But since I am lazy, or stupid, or want to make my code as clear as possible, I opted for the first definition instead.
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x)
can be reused to calculate f(x)
, as it is done in sum_2
?
Many thanks.
c++ c optimization compiler-optimization
Suppose I have a function double F(double x)
and let's assume for the sake of this example that calls to F
are costly.
Suppose I write a function f
that calculates the square root of F
:
double f(double x)
return sqrt(F(x));
and in a third function sum
I calculate the sum of f
and F
:
double sum(double x)
return F(x) + f(x);
Since I want to minimise calls to F
the above code is inefficient compared to e.g.
double sum_2(double x)
double y = F(x);
return y + sqrt(y);
But since I am lazy, or stupid, or want to make my code as clear as possible, I opted for the first definition instead.
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x)
can be reused to calculate f(x)
, as it is done in sum_2
?
Many thanks.
c++ c optimization compiler-optimization
c++ c optimization compiler-optimization
edited Mar 28 at 21:43
user1892304
asked Mar 28 at 21:06
user1892304user1892304
2671 gold badge4 silver badges10 bronze badges
2671 gold badge4 silver badges10 bronze badges
1
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
I'm not an expert on such things, but it seems to me it may depend on howF()
is defined. Does it have side effects? Can it be inlined?
– Fred Larson
Mar 28 at 21:18
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows thatF
is called two times anyway.
– ForceBru
Mar 28 at 21:20
5
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
4
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26
|
show 1 more comment
1
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
I'm not an expert on such things, but it seems to me it may depend on howF()
is defined. Does it have side effects? Can it be inlined?
– Fred Larson
Mar 28 at 21:18
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows thatF
is called two times anyway.
– ForceBru
Mar 28 at 21:20
5
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
4
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26
1
1
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
I'm not an expert on such things, but it seems to me it may depend on how
F()
is defined. Does it have side effects? Can it be inlined?– Fred Larson
Mar 28 at 21:18
I'm not an expert on such things, but it seems to me it may depend on how
F()
is defined. Does it have side effects? Can it be inlined?– Fred Larson
Mar 28 at 21:18
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows that
F
is called two times anyway.– ForceBru
Mar 28 at 21:20
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows that
F
is called two times anyway.– ForceBru
Mar 28 at 21:20
5
5
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
4
4
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26
|
show 1 more comment
3 Answers
3
active
oldest
votes
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x) can be reused to calculate f(x), as it is done in sum_2?
Maybe. Neither language requires such an optimization, and whether they allow it depends on details of the implementation of F()
. Generally speaking, different compilers behave differently with respect to this sort of thing.
It is entirely plausible that a compiler would inline function f()
into function sum()
, which would give it the opportunity to recognize that there are two calls to F(x)
contributing to the same result. In that case, if F()
has no side effects then it is conceivable that the compiler would emit only a single call to F()
, reusing the result.
Particular implementations may have extensions that can be employed to help the compiler come to such a conclusion. Without such an extension being applied to the problem, however, I rate it unlikely that a compiler would emit code that performs just one call to F()
and reuses the result.
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizessum
to have a single call toF
if it can see a definition ofF
it recognizes as pure. Even with a non-pure function (I used++y; return sin(x) * log(x);
, wherey
was an externalint
), it generated code to evaluate the pure part once and the impure part (as if) twice.
– Eric Postpischil
Mar 28 at 23:16
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likelyF()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an exampleF()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.
– John Bollinger
Mar 29 at 12:03
add a comment
|
What you're describing is called memoization, a form of (usually) run-time caching. While it's possible for this to be implemented in compilers, it's most often not performed in C compilers.
C++ does have a clever workaround for this, using the STL, detailed at this blog post from a few years ago; there's also a slightly more recent SO answer here. It's worth noting that with this approach, the compiler isn't "smartly" inferring that a function's multiple identical results will be reused, but the effect is largely the same.
Some languages, like Haskell, do feature baked-in support for compile-time memoization, but the compiler architecture is fairly different from Clang or GCC/G++.
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, insum
,F(x)
is calculated both directly and within the call tof(x)
and hence might generate code to evaluateF(x)
only once and reuse the result.
– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize thatF(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.
– Eric Postpischil
Mar 29 at 14:04
add a comment
|
Many compilers use hints to figure out if a result of a previous function call may be reused. A classical example is:
for (int i=0; i < strlen(str); i++)
Without optimizing this, the complexity of this loop is at least O(n2), but after optimization it can be O(n).
The hints that gcc, clang, and many others can take are __attribute__((pure))
and __attribute__((const))
which are described here. For example, GNU strlen
is declared as a pure function.
GCC can detect pure functions, and suggest the programmer which functions should be married pure. In fact, it does that automatically for the following simplistic example:
unsigned my_strlen(const char* str)
int i=0;
while (str[i])
++i;
return i;
unsigned word_len(const char *str)
for (unsigned i=0 ; i < my_strlen(str); ++i)
if (str[i] == ' ')
return i;
return my_strlen(str);
You can see the compilation result for gcc with -O3 -fno-inline
. It calls my_strlen(str)
only once in the whole word_len
function. Clang 7.0.0 does not seem to perform this optimization.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406843%2fwill-a-c-c-compiler-optimise-code-by-reusing-a-recently-calculated-function-re%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x) can be reused to calculate f(x), as it is done in sum_2?
Maybe. Neither language requires such an optimization, and whether they allow it depends on details of the implementation of F()
. Generally speaking, different compilers behave differently with respect to this sort of thing.
It is entirely plausible that a compiler would inline function f()
into function sum()
, which would give it the opportunity to recognize that there are two calls to F(x)
contributing to the same result. In that case, if F()
has no side effects then it is conceivable that the compiler would emit only a single call to F()
, reusing the result.
Particular implementations may have extensions that can be employed to help the compiler come to such a conclusion. Without such an extension being applied to the problem, however, I rate it unlikely that a compiler would emit code that performs just one call to F()
and reuses the result.
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizessum
to have a single call toF
if it can see a definition ofF
it recognizes as pure. Even with a non-pure function (I used++y; return sin(x) * log(x);
, wherey
was an externalint
), it generated code to evaluate the pure part once and the impure part (as if) twice.
– Eric Postpischil
Mar 28 at 23:16
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likelyF()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an exampleF()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.
– John Bollinger
Mar 29 at 12:03
add a comment
|
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x) can be reused to calculate f(x), as it is done in sum_2?
Maybe. Neither language requires such an optimization, and whether they allow it depends on details of the implementation of F()
. Generally speaking, different compilers behave differently with respect to this sort of thing.
It is entirely plausible that a compiler would inline function f()
into function sum()
, which would give it the opportunity to recognize that there are two calls to F(x)
contributing to the same result. In that case, if F()
has no side effects then it is conceivable that the compiler would emit only a single call to F()
, reusing the result.
Particular implementations may have extensions that can be employed to help the compiler come to such a conclusion. Without such an extension being applied to the problem, however, I rate it unlikely that a compiler would emit code that performs just one call to F()
and reuses the result.
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizessum
to have a single call toF
if it can see a definition ofF
it recognizes as pure. Even with a non-pure function (I used++y; return sin(x) * log(x);
, wherey
was an externalint
), it generated code to evaluate the pure part once and the impure part (as if) twice.
– Eric Postpischil
Mar 28 at 23:16
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likelyF()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an exampleF()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.
– John Bollinger
Mar 29 at 12:03
add a comment
|
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x) can be reused to calculate f(x), as it is done in sum_2?
Maybe. Neither language requires such an optimization, and whether they allow it depends on details of the implementation of F()
. Generally speaking, different compilers behave differently with respect to this sort of thing.
It is entirely plausible that a compiler would inline function f()
into function sum()
, which would give it the opportunity to recognize that there are two calls to F(x)
contributing to the same result. In that case, if F()
has no side effects then it is conceivable that the compiler would emit only a single call to F()
, reusing the result.
Particular implementations may have extensions that can be employed to help the compiler come to such a conclusion. Without such an extension being applied to the problem, however, I rate it unlikely that a compiler would emit code that performs just one call to F()
and reuses the result.
Would a C/C++ compiler optimise my code anyway by realizing that the value of F(x) can be reused to calculate f(x), as it is done in sum_2?
Maybe. Neither language requires such an optimization, and whether they allow it depends on details of the implementation of F()
. Generally speaking, different compilers behave differently with respect to this sort of thing.
It is entirely plausible that a compiler would inline function f()
into function sum()
, which would give it the opportunity to recognize that there are two calls to F(x)
contributing to the same result. In that case, if F()
has no side effects then it is conceivable that the compiler would emit only a single call to F()
, reusing the result.
Particular implementations may have extensions that can be employed to help the compiler come to such a conclusion. Without such an extension being applied to the problem, however, I rate it unlikely that a compiler would emit code that performs just one call to F()
and reuses the result.
answered Mar 28 at 21:27
John BollingerJohn Bollinger
96.7k8 gold badges48 silver badges91 bronze badges
96.7k8 gold badges48 silver badges91 bronze badges
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizessum
to have a single call toF
if it can see a definition ofF
it recognizes as pure. Even with a non-pure function (I used++y; return sin(x) * log(x);
, wherey
was an externalint
), it generated code to evaluate the pure part once and the impure part (as if) twice.
– Eric Postpischil
Mar 28 at 23:16
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likelyF()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an exampleF()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.
– John Bollinger
Mar 29 at 12:03
add a comment
|
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizessum
to have a single call toF
if it can see a definition ofF
it recognizes as pure. Even with a non-pure function (I used++y; return sin(x) * log(x);
, wherey
was an externalint
), it generated code to evaluate the pure part once and the impure part (as if) twice.
– Eric Postpischil
Mar 28 at 23:16
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likelyF()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an exampleF()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.
– John Bollinger
Mar 29 at 12:03
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizes
sum
to have a single call to F
if it can see a definition of F
it recognizes as pure. Even with a non-pure function (I used ++y; return sin(x) * log(x);
, where y
was an external int
), it generated code to evaluate the pure part once and the impure part (as if) twice.– Eric Postpischil
Mar 28 at 23:16
Re “I rate it unlikely…”: Apple LLVM 10.0.0 with clang-1000.11.45.5 optimizes
sum
to have a single call to F
if it can see a definition of F
it recognizes as pure. Even with a non-pure function (I used ++y; return sin(x) * log(x);
, where y
was an external int
), it generated code to evaluate the pure part once and the impure part (as if) twice.– Eric Postpischil
Mar 28 at 23:16
1
1
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likely
F()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an example F()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.– John Bollinger
Mar 29 at 12:03
@EricPostpischil, my estimation of likelihood is based on several things, among them a wild guess about how likely
F()
, whose evaluation is specified to be costly, is to in fact be pure or to be inlined. Your choice for an example F()
is well outside the envelope of functions I have in mind, though I grant that costliness is a relative characteristic.– John Bollinger
Mar 29 at 12:03
add a comment
|
What you're describing is called memoization, a form of (usually) run-time caching. While it's possible for this to be implemented in compilers, it's most often not performed in C compilers.
C++ does have a clever workaround for this, using the STL, detailed at this blog post from a few years ago; there's also a slightly more recent SO answer here. It's worth noting that with this approach, the compiler isn't "smartly" inferring that a function's multiple identical results will be reused, but the effect is largely the same.
Some languages, like Haskell, do feature baked-in support for compile-time memoization, but the compiler architecture is fairly different from Clang or GCC/G++.
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, insum
,F(x)
is calculated both directly and within the call tof(x)
and hence might generate code to evaluateF(x)
only once and reuse the result.
– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize thatF(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.
– Eric Postpischil
Mar 29 at 14:04
add a comment
|
What you're describing is called memoization, a form of (usually) run-time caching. While it's possible for this to be implemented in compilers, it's most often not performed in C compilers.
C++ does have a clever workaround for this, using the STL, detailed at this blog post from a few years ago; there's also a slightly more recent SO answer here. It's worth noting that with this approach, the compiler isn't "smartly" inferring that a function's multiple identical results will be reused, but the effect is largely the same.
Some languages, like Haskell, do feature baked-in support for compile-time memoization, but the compiler architecture is fairly different from Clang or GCC/G++.
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, insum
,F(x)
is calculated both directly and within the call tof(x)
and hence might generate code to evaluateF(x)
only once and reuse the result.
– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize thatF(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.
– Eric Postpischil
Mar 29 at 14:04
add a comment
|
What you're describing is called memoization, a form of (usually) run-time caching. While it's possible for this to be implemented in compilers, it's most often not performed in C compilers.
C++ does have a clever workaround for this, using the STL, detailed at this blog post from a few years ago; there's also a slightly more recent SO answer here. It's worth noting that with this approach, the compiler isn't "smartly" inferring that a function's multiple identical results will be reused, but the effect is largely the same.
Some languages, like Haskell, do feature baked-in support for compile-time memoization, but the compiler architecture is fairly different from Clang or GCC/G++.
What you're describing is called memoization, a form of (usually) run-time caching. While it's possible for this to be implemented in compilers, it's most often not performed in C compilers.
C++ does have a clever workaround for this, using the STL, detailed at this blog post from a few years ago; there's also a slightly more recent SO answer here. It's worth noting that with this approach, the compiler isn't "smartly" inferring that a function's multiple identical results will be reused, but the effect is largely the same.
Some languages, like Haskell, do feature baked-in support for compile-time memoization, but the compiler architecture is fairly different from Clang or GCC/G++.
edited Mar 28 at 21:36
answered Mar 28 at 21:27
0xdd0xdd
2042 silver badges15 bronze badges
2042 silver badges15 bronze badges
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, insum
,F(x)
is calculated both directly and within the call tof(x)
and hence might generate code to evaluateF(x)
only once and reuse the result.
– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize thatF(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.
– Eric Postpischil
Mar 29 at 14:04
add a comment
|
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, insum
,F(x)
is calculated both directly and within the call tof(x)
and hence might generate code to evaluateF(x)
only once and reuse the result.
– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize thatF(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.
– Eric Postpischil
Mar 29 at 14:04
2
2
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, in
sum
, F(x)
is calculated both directly and within the call to f(x)
and hence might generate code to evaluate F(x)
only once and reuse the result.– Eric Postpischil
Mar 28 at 23:04
The question does not describe memoization. Memoization is one technique that could speed up computation, possibly in the circumstances described in the question, but the question asks about reusing previously calculated results in general, not memoization. It is much more likely that a compiler might recognize that, in
sum
, F(x)
is calculated both directly and within the call to f(x)
and hence might generate code to evaluate F(x)
only once and reuse the result.– Eric Postpischil
Mar 28 at 23:04
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
@EricPostpischil this is a good point; do you know any compilers that currently do this?
– 0xdd
Mar 29 at 12:46
Do what, recognize that
F(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.– Eric Postpischil
Mar 29 at 14:04
Do what, recognize that
F(x)
is evaluated twice? As noted in my comment on John Bollinger’s answer, Clang does, and I expect other good quality compilers do too.– Eric Postpischil
Mar 29 at 14:04
add a comment
|
Many compilers use hints to figure out if a result of a previous function call may be reused. A classical example is:
for (int i=0; i < strlen(str); i++)
Without optimizing this, the complexity of this loop is at least O(n2), but after optimization it can be O(n).
The hints that gcc, clang, and many others can take are __attribute__((pure))
and __attribute__((const))
which are described here. For example, GNU strlen
is declared as a pure function.
GCC can detect pure functions, and suggest the programmer which functions should be married pure. In fact, it does that automatically for the following simplistic example:
unsigned my_strlen(const char* str)
int i=0;
while (str[i])
++i;
return i;
unsigned word_len(const char *str)
for (unsigned i=0 ; i < my_strlen(str); ++i)
if (str[i] == ' ')
return i;
return my_strlen(str);
You can see the compilation result for gcc with -O3 -fno-inline
. It calls my_strlen(str)
only once in the whole word_len
function. Clang 7.0.0 does not seem to perform this optimization.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret
add a comment
|
Many compilers use hints to figure out if a result of a previous function call may be reused. A classical example is:
for (int i=0; i < strlen(str); i++)
Without optimizing this, the complexity of this loop is at least O(n2), but after optimization it can be O(n).
The hints that gcc, clang, and many others can take are __attribute__((pure))
and __attribute__((const))
which are described here. For example, GNU strlen
is declared as a pure function.
GCC can detect pure functions, and suggest the programmer which functions should be married pure. In fact, it does that automatically for the following simplistic example:
unsigned my_strlen(const char* str)
int i=0;
while (str[i])
++i;
return i;
unsigned word_len(const char *str)
for (unsigned i=0 ; i < my_strlen(str); ++i)
if (str[i] == ' ')
return i;
return my_strlen(str);
You can see the compilation result for gcc with -O3 -fno-inline
. It calls my_strlen(str)
only once in the whole word_len
function. Clang 7.0.0 does not seem to perform this optimization.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret
add a comment
|
Many compilers use hints to figure out if a result of a previous function call may be reused. A classical example is:
for (int i=0; i < strlen(str); i++)
Without optimizing this, the complexity of this loop is at least O(n2), but after optimization it can be O(n).
The hints that gcc, clang, and many others can take are __attribute__((pure))
and __attribute__((const))
which are described here. For example, GNU strlen
is declared as a pure function.
GCC can detect pure functions, and suggest the programmer which functions should be married pure. In fact, it does that automatically for the following simplistic example:
unsigned my_strlen(const char* str)
int i=0;
while (str[i])
++i;
return i;
unsigned word_len(const char *str)
for (unsigned i=0 ; i < my_strlen(str); ++i)
if (str[i] == ' ')
return i;
return my_strlen(str);
You can see the compilation result for gcc with -O3 -fno-inline
. It calls my_strlen(str)
only once in the whole word_len
function. Clang 7.0.0 does not seem to perform this optimization.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret
Many compilers use hints to figure out if a result of a previous function call may be reused. A classical example is:
for (int i=0; i < strlen(str); i++)
Without optimizing this, the complexity of this loop is at least O(n2), but after optimization it can be O(n).
The hints that gcc, clang, and many others can take are __attribute__((pure))
and __attribute__((const))
which are described here. For example, GNU strlen
is declared as a pure function.
GCC can detect pure functions, and suggest the programmer which functions should be married pure. In fact, it does that automatically for the following simplistic example:
unsigned my_strlen(const char* str)
int i=0;
while (str[i])
++i;
return i;
unsigned word_len(const char *str)
for (unsigned i=0 ; i < my_strlen(str); ++i)
if (str[i] == ' ')
return i;
return my_strlen(str);
You can see the compilation result for gcc with -O3 -fno-inline
. It calls my_strlen(str)
only once in the whole word_len
function. Clang 7.0.0 does not seem to perform this optimization.
word_len:
mov rcx, rdi
call my_strlen ; <-- this is the only call (outside any loop)
test eax, eax
je .L7
xor edx, edx
cmp BYTE PTR [rcx], 32
lea rdi, [rdi+1]
jne .L11
jmp .L19
.L12:
add rdi, 1
cmp BYTE PTR [rdi-1], 32
je .L9
.L11:
add edx, 1
cmp eax, edx
jne .L12
.L7:
ret
.L19:
xor edx, edx
.L9:
mov eax, edx
ret
edited Mar 29 at 21:27
answered Mar 28 at 22:43
Michael VekslerMichael Veksler
6,2321 gold badge9 silver badges26 bronze badges
6,2321 gold badge9 silver badges26 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406843%2fwill-a-c-c-compiler-optimise-code-by-reusing-a-recently-calculated-function-re%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Which compiler? So long as the code produces the same result (and side-effects), the compiler can do what it pleases.
– Weather Vane
Mar 28 at 21:14
I'm not an expert on such things, but it seems to me it may depend on how
F()
is defined. Does it have side effects? Can it be inlined?– Fred Larson
Mar 28 at 21:18
If you would like to know how compilers see your code, take a look at Compiler Explorer. This shows that
F
is called two times anyway.– ForceBru
Mar 28 at 21:20
5
Aside from the interesting academic question of "will it be optimised?", may I suggest you don't write code that relies on the optimisation. If I'm doing code review, and I see an expensive function that looks like it's called more than necessary, that's a huge code smell. I don't want to think about the details of the compiler optimisations, I want to see code that is clear and clearly performant. Remember too, the person reviewing your code may be you in 6 months time.
– JMAA
Mar 28 at 21:24
4
write for readability. Only when you measured you can know if it is worth to compromise for efficiency, but to measure you need a running program first ;)
– formerlyknownas_463035818
Mar 28 at 21:26