Sonic78
Sonic78

Reputation: 808

C99: Is an inlined function still a sequence point?

Adding inline to a function suggests the compiler that calls to the function be as fast as possible. (ISO/IEC 9899:1999 §6.7.4.5)

Dependent on the optimization level, a compiler might also decide to "inline" a function (substitute the call with its instructions).

ISO/IEC 9899:1999 defines in Annex C "Sequence points" / §5.1.2.3 that

The call to a function, after the arguments have been evaluated (6.5.2.2).

(and others) as a sequence point.

My Questions:

  1. What defines the C99 abstract machine in terms of function calls that have been optimized by inlining? Do these sequence points need to be retained even if the optimization removes the call?
  2. What is the behavior of typical embedded C compilers in C99 mode when aggressive optimization is used?

Upvotes: 8

Views: 372

Answers (2)

Lundin
Lundin

Reputation: 214770

... (and others) as a sequence point.

There are no other guaranteed sequence points except that one - after argument evaluation but before the function is called. Same goes for an inlined function. Except in case of inlining, argument evaluation may or may not get carried out depending on if that evaluation contains needed side effects or not (explained further below).

The function may or may not have full expressions as defined in Annex C, in which case there are sequence points inside the function body.


  1. What defines the C99 abstract machine in terms of function calls that have been optimized by inlining? Do these sequence points need to be retained even if the optimization removes the call?

In general - not specific to C99 nor inlined functions - the C standard speaks of needed side effects, for example C99 5.1.2.3 (emphasis mine):

In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).

Sequence points aren't "holy", only needed side effects are. A needed side effect cannot get optimized out, but it can be optimized to run faster, it can be re-ordered across sequence points etc etc.

The only side effect that can neither get optimized nor reordered is a volatile access. In case an access to a volatile object happens, the compiler must carry out that evaluation and do so before the next sequence point present, meaning in that specific scenario, the sequence point is respected. In C23 this is phrased as "volatile accesses to objects are evaluated strictly according to the rules of the abstract machine."

For every other situation, the compiler is free to carry out the above quoted optimization. It is also free to do instruction re-ordering across sequence points, as long as that doesn't affect the program behavior.

For example leave out the whole function call, skip writes to local variables that aren't used ("needed") by the caller, re-order the function call etc etc. Those optimizations are possible regardless of inlining.

The only thing that inlining makes different is that a normal function defined elsewhere with external linkage can't make assumptions of the state of parameters on the caller side. Therefore function call arguments usually need to be both evaluated and copied into a temporary location before the function is called. But when the function is inlined, the compiler may draw further conclusions about the variables used as arguments and optimize accordingly.


  1. What is the behavior of typical embedded C compilers in C99 mode when aggressive optimization is used.

Same as for any other compiler. When the function is inlined, the function call is skipped, as is the parameter passing part according to the ABI. The variables that would have been passed can still be stored wherever the compiler already stored them, for example in fast registers rather than on the stack if the function call ABI required that. Meaning that there may be extra benefits in performance beyond just leaving out the function call overhead.

Though historically, various more or less exotic embedded system compilers did a lousy job of optimizing code in general. Many also suffer from poor C conformance. Many of these compilers are still on the market.

Upvotes: 10

n. m. could be an AI
n. m. could be an AI

Reputation: 120059

5.1.2.3 Program execution

  1. The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.

Upvotes: 3

Related Questions