Microchip ICD4 ?

Obviously it is not possible to compare exact outputs without using the same target devices. But it would seem that you are getting roughly the same kind of optimisations - but with a good deal more manual work. Still, it is nice to see that it is possible to do this in Forth too.

Reply to
David Brown
Loading thread data ...

It is likely that this is standard startup code. In my tests, I omitted that - but by default you'll get code to clear the bss, copy initialised data, etc. That is all fixed overhead in a normal program, and any serious assembly code will need something similar. (On my testing, that common code was around 80 bytes, not 312 bytes, but details will vary by compiler.)

If compiler flags "optimise away" your code, you don't understand how to program in C.

Reply to
David Brown

Correct.

If you try to write something in English, and you spell it incorrectly, whose fault is it? If you try to write something in assembly but get the instructions wrong, whose fault is it?

If you try to write something in C, but do not know how to do so correctly, then it is /not/ the compiler's fault - it is /your/ fault.

Yes, it is /your/ fault. And if your tools don't spot such mistakes automatically, it is /your/ fault for not understanding how to use your tools properly. Just like when you hit your thumb with a hammer - it is not the fault of the hammer or the nail.

If you want to use a tool, learn how to do so. Compilers are not mysterious or malicious - it is just that some users are incompetent.

Reply to
David Brown

On that link what an annoying writing style, same paragraph over an over making minor changes to the paragraph sometimes repeating minor variations of a paragraph ten times.

--
Cecil - k5nwa
Reply to
Cecil Bayona

The type system also helps with alias analysis, getting rid of unneeded loads and stores. I don't see how a Forth compiler can do that.

Reply to
Paul Rubin

In C++ you shouldn't even be using the "==" operator on the basic literal types most of the time, anyway. It means your types aren't strong enough. You shouldn't ever be able to have -5000 pieces of gold or be 350 years old.

Instead you have classes which encapsulate and sanitize your user data. In C++1x:

auto player_1_gold = player_gold_t{500}; //player1 has 500 gold auto player_2_gold = player_gold_t{1000}; //player2 has 1000 gold

So this works (assuming appropriately overloaded "==" operator):

player_1_gold == player_2_gold ? ...etc. //OK

But you define your copy constructor and user defined integer-conversion operator "explicit" to make stuff like this illegal:

if (player_1_gold = 1000) //Compiler error, can't assign "500 int" to a "player_gold_t"

if (player_1_gold == 500) //Compiler error, No implicit comparison possible between "500 int" and "player_gold_t"

if (player_1_gold = player_2_gold) //Compiler error, no implicit conversion from "player_gold_t" to "bool"

if (player_1_gold == static_cast(500)) //OK

void foo(unsigned int bar) {...

foo(player_1_gold); //Compiler error, no implicit conversion from player_gold_t to "unsigned int"

auto player_3_gold = player_2_gold //Compiler error, Copy constructor marked "explicit", direct initialization of "player_3_gold" from "player_2_gold" not possible

auto player_3_gold{player_2_gold}; //OK, player_3_gold initialized from player_2_gold's value

...

And this should all compile down to have no overhead as compared with the same operations written in straight C.

That is to say, if you get it wrong nowadays with modern C++ the "donkey" is _you_. It's the programmer's job to write sane code, not for the compiler to divine what it thinks you mean.

Reply to
bitrex

They are lecture slides. The idea is the audience sees the paragraph morphing on the screen while the speaker gives the talk.

Reply to
Paul Rubin

That was silly, just profile the code to see where the bottlenecks are and rewrite those parts. No point in rewriting code for efficiency that the CPU is only spending 1% of its time executing (usually 90% of the codebase)

Reply to
bitrex

It doesn't. What you mean is: By (often wrongly) assuming that C programs don't access data through pointers of other types, adversarial C compilers save themselves the trouble of trying to do proper alias analysis. But of course, the result is often wrong, because the assumption is often wrong.

The Forth *programmer* gets rid of unneeded loads and stores by not writing them.

- anton

--
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html 
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html 
     New standard: http://www.forth200x.org/forth200x.html 
   EuroForth 2017: http://euro.theforth.net/
Reply to
Anton Ertl

[...]

Yeah, right. Too bad you were not consulted when they made the decision, you would have saved the company a lot of time and money. Although, thinking about it, if, say, a 30M-cycle run takes 100,000s on the first simulator, and 1,000s of that is spent in 90% of the code, and you manage to speed up the other 10% by a factor of 99, the result will still take 2,000s for the run, while the new simulator takes 10s.

Anyway, with the "crazy contorted optimizations that the compiler puts in", such that "C++ will likely beat handwritten assembler for any sizeable program", the C++ compiler should have optimized the original simulator to be as fast as the final simulator all by itself. It didn't, so the"crazy contorted optimizations" may be crazy and contorted, but are not up to the task of competing with source-level optimizations.

- anton

--
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html 
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html 
     New standard: http://www.forth200x.org/forth200x.html 
   EuroForth 2017: http://euro.theforth.net/
Reply to
Anton Ertl

Too true :( Plus the programmer often lies.

What /is/ the consequence of one compilation unit "casting away the constness" of something defined in another compilation unit?

Reply to
Tom Gardner

"Undefined behavior" which is highly application-specific. Anything from no ill effect, to incorrect output (either immediately or at some later time), to terrible data corruption, to a quick crash/segfault.

In extreme cases, things like "destruction of hardware" and "loss of life" can occur.

I once took advantage of a compiler bug in a Univac FORTRAN system, to demonostrate to my doubting FORTRAN instructor that the computer believed that two plus two equals six. I incremented the value of a parameter which was passed into a FORTRAN function (and FORTRAN of the era always passed all parameters by reference, not by value). Since I'd passed a constant "2", and since the compiler hadn't bothered either to memory-protect the constant or provide an emphermeral copy... foom.

The "all constants are variable" rule took hold. :-)

Reply to
Dave Platt

Those were someone else's words, not mine! ;-)

It's always possible to write inefficient algorithms in any compiled language that will compile to well-optimized (for the algorithm) but inefficient (for the application) code.

For the comparison to make any sense you have to make the assumption that the engineer is not doing bonehead things like say making thousands of superfluous copies of a large object per second when a simple move would suffice. Unfortunately in general that's easier to do in a language with OOP-features like C++ than straight asm. That particular problem has become less of an issue in the later versions of the standard with move constructors and copy elision/RVO.

Reply to
bitrex

Vaguely specified ones, that differ from compiler to compiler and often depend on cmdline switches.

Reply to
Johann Klammer

I once had a subroutine that was passed a boolean (LOGICAL as they call it) , that I set to FALSE after inspection. When I inadvertantly called this with a TRUE literal, TRUE was turned into FALSE for all of FORTRAN and hell broke loose.

At the time it was considered a bug in the program not in the compiler.

Anyway the specification of C++ and its standard library is such that no single expert is master of it all. Regularly conflicts are detected between remote parts of it. Bottomline, not a language for mission critical stuff or cancer radiation equipment.

There are more important things than a little speed.

Groetjes Albert

--
Albert van der Horst, UTRECHT,THE NETHERLANDS 
Economic growth -- being exponential -- ultimately falters. 
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
Reply to
Albert van der Horst

It's used in that stuff all the time, though. The list of undefined/implementation-defined behavior is not infinite.

And in 2k17 if one is consistently running into issues with undefined behavior it probably means You're Doing It Wrong, i.e. you're not really writing C++, you're trying to write "C with Classes." There's all kinds of stuff in C++1x to support backward compatibility that one should never actually use in new code.

i.e. memset is obsolete. memcpy is obsolete. all those "mem" functions are obsolete. Doing any kind of direct byte-for-byte copy of structures is pretty much obsolete.

C-style unions are pretty much obsolete, you use a std::variant type. C-style arrays are obsolete, I never use them. If you need a plain ol' const array you use a std::array. If you need a list of stuff you can modify you use a std::vector. Raw pointers are pretty much obsolete except for when you need to make a user-defined conversion to pass something to a C API call that can only accept pointers. "Naked" "new" and "delete" are obsolete unless you're writing a custom allocator.

"For" loops that increment counters are obsolete...etc.

Reply to
bitrex

Part of the problem is that I think some coders think you still have to write C++ nowadays "sorta like C" to get C-like performance. Which is Wrong

Reply to
bitrex

One of the driving ideas of C++ is to provide useful abstractions at essentially zero cost. Evidently it wasn't used that way in that first implementation. Was it written in C++1x (i.e. C++11 or later)? C++11 made it much easier to do certain important things efficently, by introducing move constructors.

It could be that the first implementation was intended as a prototype. I probably would have done it in Python or Haskell, so it would have been even slower, but allowed easier instrumentation and exploration.

Anyway, you can write bad code in any language.

Reply to
Paul Rubin

Well, I'm thinking partly of the restrict keyword introduced in C99, which explicitly tells the compiler that there's no alias.

That's true, accessing data through pointers of multiple types is not allowed in C, so it's unsurprising that programmers who make wrong assumptions to the contrary can get wrong results. Wrong assumptions are the cause of plenty of bugs no matter what language is used.

That requires close manual control over large stretches of code, that a real compiler automates.

Reply to
Paul Rubin

Fortran historically passed parameters by copy-restore (not by reference), so the compiler did a permissible thing in your example.

Reply to
Paul Rubin

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.