Tcc code surprised me by being very slow and then some tcc code surprised me by being fast

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Tcc code surprised me by being very slow and then some tcc code surprised me by being fast

Joshua Scholar
I'm having fun getting to know the code, and writing features for tcc that I make sure don't require large changes to the project and that my additions themselves compile in tcc.

But when I tested a hash function, I was disheartened to find that spooky hash runs about 1/10 the speed compiled in tcc as compiled in gcc.   Although gcc compiled with a no optimization setting makes code that runs near the same speed as code compiled under tcc. 

So I started thinking that for the project I'm working on maybe I'd do better to be learning to use LLVM than working on this.

But since I wondered, well maybe tcc is bad at heavily optimizable loops, but maybe it's ok on general code.

So I took a copy of tcc that had been compiled with the microsoft compiler and used it to compile itself, which of course goes MUCH faster than compiling it with microsoft.

Then I took the version of tcc that had been compiled under tcc and used it to compile itself.

And it still compiled so fast that I can hardly feel the difference.  I don't THINK it was 10 times slower.

So strange to be both impressed at how slow tcc's code is and how fast tcc's code is within an hour.

Joshua Scholar

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Tcc code surprised me by being very slow and then some tcc code surprised me by being fast

Samir Ribić
Well, tcc is one of the fastest C compilers when we speak about *compilation speed*. However, this is achieved by generating code almost simultaneously with syntax analysis, without intermediate steps that use some other compilers. Compilers like gcc do the following:
- Perform syntax analysis and generate abstract syntax tree
- Perform semantic analysis over the tree
- Optimize the tree
- Generate intermediate code
- Optimize intermediate code
- Generate assembly code
- Optimize assembly code
- Generate machine code
- Link to executable using external linker

Tcc does not generate intermediate tree and platform neutral code. It has workflow more similar to the following
- While analysing the syntax check the semantics and generate the required tables. If the syntax is correct, then generate machine code. immediately
- Use internal linker and link with simple startup routine

The result is much faster compilation and often shorter executable due to simple startup routine. 

However, this also means that tcc can not be the fastest C compiler when we speak about *execution speed*. For example. it is impossible to detect dead code. Look at this code
a=200;
b=10;
a=b;
Remark that first instruction is completely useless. The compilers who generate intermediate formats can detect it and remove this instruction from generated code.

Similarly, sometimes variables do not need to be stored in  memory like this loop counter "i":
for (int i=0;i<n;i++) pow=pow*b;
After we remarked that the loop counter is used just to repeat multiplication n times, it is possible to generate machine code LOOP instruction with register counter, which is quite fast. Unfortunately, the compiler can not remark it without analysing the whole source file before generating assembly code. 

Should we make tcc to perform more like gcc and generate faster code? No! Adding intermediate formats and infinite optimizations will nullify two good tcc properties, fast compilation and small compiler size. However, I would like to see some simple code generating improvements, which are possible without changes in compiler design. For example, operations between variable and constant like a=5;  a>5;  a+5  etc  on 80386 can be done using one instruction while tcc generates two instructions.


On Sat, Dec 26, 2020 at 9:05 PM Joshua Scholar <[hidden email]> wrote:
I'm having fun getting to know the code, and writing features for tcc that I make sure don't require large changes to the project and that my additions themselves compile in tcc.

But when I tested a hash function, I was disheartened to find that spooky hash runs about 1/10 the speed compiled in tcc as compiled in gcc.   Although gcc compiled with a no optimization setting makes code that runs near the same speed as code compiled under tcc. 

So I started thinking that for the project I'm working on maybe I'd do better to be learning to use LLVM than working on this.

But since I wondered, well maybe tcc is bad at heavily optimizable loops, but maybe it's ok on general code.

So I took a copy of tcc that had been compiled with the microsoft compiler and used it to compile itself, which of course goes MUCH faster than compiling it with microsoft.

Then I took the version of tcc that had been compiled under tcc and used it to compile itself.

And it still compiled so fast that I can hardly feel the difference.  I don't THINK it was 10 times slower.

So strange to be both impressed at how slow tcc's code is and how fast tcc's code is within an hour.

Joshua Scholar
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Tcc code surprised me by being very slow and then some tcc code surprised me by being fast

Joshua Scholar
I was just looking at a few projects that want to generate code quickly but in reasonable quality.

This post here about a jit compiler project (as yet unfinished), says that for GCC there are about 300 passes, but that most of those don't buy you much.

But he wrote "Recently, I did an experiment by switching on only a fast and simple RA and combiner in GCC. There are no options to do this, I needed to modify GCC. (I can provide a patch if somebody is interested.) Compared to hundreds of optimizations in GCC-9.0 with -O2, these two optimizations achieve almost 80% performance on an Intel i7-9700K machine under Fedora Core 29 for real-world programs through SpecCPU, one of the most credible compiler benchmark suites..."

So, turning on only two, admittedly involved, optimization passes got him 70% of the speed of GCC -O2 on spec cpu.

So maybe a well chosen optimization layer would be worthwhile.  His project is interesting, it intends to implement a compiler orders of magnitude faster than LLVM's own jit, which could probably gain real world speed ups of several times just by getting rid of the start-up lag (it takes a lot of book keeping in LLVM before it can start a compilation).



On Sun, Dec 27, 2020 at 3:32 AM Samir Ribić <[hidden email]> wrote:
Well, tcc is one of the fastest C compilers when we speak about *compilation speed*. However, this is achieved by generating code almost simultaneously with syntax analysis, without intermediate steps that use some other compilers. Compilers like gcc do the following:
- Perform syntax analysis and generate abstract syntax tree
- Perform semantic analysis over the tree
- Optimize the tree
- Generate intermediate code
- Optimize intermediate code
- Generate assembly code
- Optimize assembly code
- Generate machine code
- Link to executable using external linker

Tcc does not generate intermediate tree and platform neutral code. It has workflow more similar to the following
- While analysing the syntax check the semantics and generate the required tables. If the syntax is correct, then generate machine code. immediately
- Use internal linker and link with simple startup routine

The result is much faster compilation and often shorter executable due to simple startup routine. 

However, this also means that tcc can not be the fastest C compiler when we speak about *execution speed*. For example. it is impossible to detect dead code. Look at this code
a=200;
b=10;
a=b;
Remark that first instruction is completely useless. The compilers who generate intermediate formats can detect it and remove this instruction from generated code.

Similarly, sometimes variables do not need to be stored in  memory like this loop counter "i":
for (int i=0;i<n;i++) pow=pow*b;
After we remarked that the loop counter is used just to repeat multiplication n times, it is possible to generate machine code LOOP instruction with register counter, which is quite fast. Unfortunately, the compiler can not remark it without analysing the whole source file before generating assembly code. 

Should we make tcc to perform more like gcc and generate faster code? No! Adding intermediate formats and infinite optimizations will nullify two good tcc properties, fast compilation and small compiler size. However, I would like to see some simple code generating improvements, which are possible without changes in compiler design. For example, operations between variable and constant like a=5;  a>5;  a+5  etc  on 80386 can be done using one instruction while tcc generates two instructions.


On Sat, Dec 26, 2020 at 9:05 PM Joshua Scholar <[hidden email]> wrote:
I'm having fun getting to know the code, and writing features for tcc that I make sure don't require large changes to the project and that my additions themselves compile in tcc.

But when I tested a hash function, I was disheartened to find that spooky hash runs about 1/10 the speed compiled in tcc as compiled in gcc.   Although gcc compiled with a no optimization setting makes code that runs near the same speed as code compiled under tcc. 

So I started thinking that for the project I'm working on maybe I'd do better to be learning to use LLVM than working on this.

But since I wondered, well maybe tcc is bad at heavily optimizable loops, but maybe it's ok on general code.

So I took a copy of tcc that had been compiled with the microsoft compiler and used it to compile itself, which of course goes MUCH faster than compiling it with microsoft.

Then I took the version of tcc that had been compiled under tcc and used it to compile itself.

And it still compiled so fast that I can hardly feel the difference.  I don't THINK it was 10 times slower.

So strange to be both impressed at how slow tcc's code is and how fast tcc's code is within an hour.

Joshua Scholar
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Tcc code surprised me by being very slow and then some tcc code surprised me by being fast

Joshua Scholar
In reply to this post by Samir Ribić

On Sun, Dec 27, 2020 at 3:32 AM Samir Ribić <[hidden email]> wrote:
Well, tcc is one of the fastest C compilers when we speak about *compilation speed*. However, this is achieved by generating code almost simultaneously with syntax analysis, without intermediate steps that use some other compilers. Compilers like gcc do the following:
- Perform syntax analysis and generate abstract syntax tree
- Perform semantic analysis over the tree
- Optimize the tree
- Generate intermediate code
- Optimize intermediate code
- Generate assembly code
- Optimize assembly code
- Generate machine code
- Link to executable using external linker

Tcc does not generate intermediate tree and platform neutral code. It has workflow more similar to the following
- While analysing the syntax check the semantics and generate the required tables. If the syntax is correct, then generate machine code. immediately
- Use internal linker and link with simple startup routine

The result is much faster compilation and often shorter executable due to simple startup routine. 

However, this also means that tcc can not be the fastest C compiler when we speak about *execution speed*. For example. it is impossible to detect dead code. Look at this code
a=200;
b=10;
a=b;
Remark that first instruction is completely useless. The compilers who generate intermediate formats can detect it and remove this instruction from generated code.

Similarly, sometimes variables do not need to be stored in  memory like this loop counter "i":
for (int i=0;i<n;i++) pow=pow*b;
After we remarked that the loop counter is used just to repeat multiplication n times, it is possible to generate machine code LOOP instruction with register counter, which is quite fast. Unfortunately, the compiler can not remark it without analysing the whole source file before generating assembly code. 

Should we make tcc to perform more like gcc and generate faster code? No! Adding intermediate formats and infinite optimizations will nullify two good tcc properties, fast compilation and small compiler size. However, I would like to see some simple code generating improvements, which are possible without changes in compiler design. For example, operations between variable and constant like a=5;  a>5;  a+5  etc  on 80386 can be done using one instruction while tcc generates two instructions.


On Sat, Dec 26, 2020 at 9:05 PM Joshua Scholar <[hidden email]> wrote:
I'm having fun getting to know the code, and writing features for tcc that I make sure don't require large changes to the project and that my additions themselves compile in tcc.

But when I tested a hash function, I was disheartened to find that spooky hash runs about 1/10 the speed compiled in tcc as compiled in gcc.   Although gcc compiled with a no optimization setting makes code that runs near the same speed as code compiled under tcc. 

So I started thinking that for the project I'm working on maybe I'd do better to be learning to use LLVM than working on this.

But since I wondered, well maybe tcc is bad at heavily optimizable loops, but maybe it's ok on general code.

So I took a copy of tcc that had been compiled with the microsoft compiler and used it to compile itself, which of course goes MUCH faster than compiling it with microsoft.

Then I took the version of tcc that had been compiled under tcc and used it to compile itself.

And it still compiled so fast that I can hardly feel the difference.  I don't THINK it was 10 times slower.

So strange to be both impressed at how slow tcc's code is and how fast tcc's code is within an hour.

Joshua Scholar
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel
_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel