7 ms·
for (int i=param; i < param + 16; i++) does not have a guaranteed loop count with the current rules. The loop body will execute 16 times if param <= INT_MAX-16
by _kst_ 5y ago
for (int i=param; i < param + 16; i++)
does not have a guaranteed loop count with the current rules. The loop body will execute 16 times if param <= INT_MAX-16, but if the expression "param + 16" can overflow, the behavior is undefined. (I'm assuming param is of type int.)
- BruiseLee 5y agoThe compiler is allowed to act as if this loop executes exactly 16 times. That means it could unroll and vectorize it for example.
- vyodaiken 5y agoIt is completely useless to allow compilers to assume false things about the code they generate.
- fooker 5y agoIt’s not useless. The assumption is not false if the program doesn’t have undefined behavior. The assumption allows the code to be a few times faster. To disallow this assumption would inhibit these optimizations.
- msbarnett 5y ago> does not have a guaranteed loop count with the current rules. The loop body will execute 16 times if param <= INT_MAX-16, but if the expression "param + 16" can overflow, the behavior is undefined. (I'm assuming param is of type int.) And the standard permits us (among other responses) to ignore undefined behaviour, so it does have a guaranteed loop count under a reading of the standard which the standard specifically and explicitly allows.
- dooglius 5y agoEither the limit on param is guaranteed in some way by the rest of the program, or it is not. If it is, then the loop count is guaranteed in both cases. If it is not, the loop count is not guaranteed in either case.
- msbarnett 5y agoThat you wish that the C Standard mandated this interpretation does not change the fact that this is not what the C Standard says.
- dooglius 5y agoYou are mistaken, the C standard is quite clear that it does not make any guarantees regarding the behavior of programs that exhibit undefined behavior, and that signed integer overflow is undefined behavior.
- masklinn 5y agoThey're not mistaken. What compilers will do is assume that UB don't happen. If no UB happens, that means `param + 16` never overflowed, therefore there are always exactly 16 operations.
- _kst_ 5y agoOr they assume "param + 16" will never overflow, so they emit an ADD instruction and use whatever result it yields. Saying that a compiler "assumes" anything is anthropomorphic. A compiler may behave (generate code) in a manner that does not take the presence or absence of undefined behavior into account. If you just say it assumes something, that doesn't tell you what it will do based on that assumption. Generating code that yields exactly 16 iterations is one of infinitely many possible consequences of undefined behavior. If the mathematical value of `param + 16` exceeds `INT_MAX`, then the code has undefined behavior. The C standard says nothing at all about how the program will behave. A conforming compiler can generate code that iterates 42 times and then whistles Dixie. The non-normative note under the definition of "undefined behavior" does not constrain what a conforming implementation is allowed to do. "imposes no requirements" means "imposes no requirements".
- anarazel 5y agoThat's precisely my point? Because the overflow case is undefined, the compiler can assume it doesn't happen and optimize based on the fixed loop count.
- rurban 5y agoThe overflow case is not UB. param can be unsigned, of fwrapv may be declared. Or the compiler chooses to declare fwrapv by default. In no case is the compiler allowed to declare the overflow away, unless it knows from before that param can not overflow. The optimization on loop count 16 can still happen with a runtime guard.
- OskarS 5y agoThe loop counter is signed even if param is not, so i++ could overflow. fwrapv is a compiler flag, it is not part of the standard: it is a flag that mandates a certain behaviour in this case, but in standard C, the loop variable overflowing is definitely UB. No runtime guard needed, C compilers are just allowed to assume a fixed length. This is the whole reason signed overflow is UB in C, for exactly cases like this.
- _kst_ 5y agoIf param is unsigned, then "param + 16" cannot overflow; rather, the value wraps around in a language-defined manner. I've been assuming that param is of type int (and I stated that assumption).