We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
1.when i use printf with no var_args then the compiler should call puts instead of printf.
ex1:
#include <REGX51.H> #include <stdio.h> void main(void) { printf("This must call puts instead of printf"); }
Program Size: data=30.1 xdata=0 code=1103
ex2:
#include <REGX51.H> #include <stdio.h> void main(void) { puts("This must call puts instead of printf"); }
Program Size: data=9.0 xdata=0 code=168
The above code links the printf function from the library which is huge(produces 1103 bytes).But the compiler can use puts when there is no var_args given which is much smaller than printf(produces 168 bytes).
2.The Compiler must find and remove the duplicate constant strings
ex3:
#include <REGX51.H> #include <stdio.h> void main(void) { puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); puts("This string gets duplicated as many time as i use it"); }
Program Size: data=9.0 xdata=0 code=334
ex4:
#include <REGX51.H> #include <stdio.h> void main(void) { puts("This string gets duplicated as many time as i use it"); }
Program Size: data=9.0 xdata=0 code=183
3.Bit Test instructions are not used when i actually test for the bit
ex5:
#include <REGX51.H> #include <stdio.h> void main(void) { if(P0^1) { P1 = 10; } } ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION main (BEGIN) ; SOURCE LINE # 6 ; SOURCE LINE # 7 ; SOURCE LINE # 8 0000 E580 MOV A,P0 0002 6401 XRL A,#01H 0004 6003 JZ ?C0002 ; SOURCE LINE # 9 ; SOURCE LINE # 10 0006 75900A MOV P1,#0AH ; SOURCE LINE # 11 ; SOURCE LINE # 13 0009 ?C0002: 0009 22 RET ; FUNCTION main (END)
In the above assembly output it should have used a single instruction JNB instead of three MOV,XRL and JZ.This is very basic anybody would object the assembly code produced.
I have not used the compiler much.But the compiler needs a look by the programmers at keil.
The above programs were all compiled with compiler optimisation level set to 9 & favour speed.
About 5 years back i compiled a c51 source code using keil. Now i recompiled the same source code with the latest compiler from keil and compared the two output .hex files. Unfortunately it produced exactly the same output.Here i was expecting some code and data size reduction as the compiler must be capable of optimising more.
It seems there was no improvement on the compiler side.
It is not a complaint but in the interest of improving the compiler.
regards,
S.Sheik mohamed
The linker, you mean. And I don't think this is a correct statement.
But the compiler needs a look by the programmers at keil
No dear Sheik: you need to know what you're doing and what you're talking about, before making baseless accusations!
Tamir, I've seen compilers replace calls to printf with puts. IIRC it was Visual C++. You'll have a hard time arguing that this would be a useless optimization. And why are you accusing the OP of not knowing what he is talking about? His point is that the compiler doesn't implement many common optimization techniques found in many other compilers. And he is right. I don't think that writing about it in forums will change anything, but that's a different matter.
You'll have a hard time arguing that this would be a useless optimization.
Actually, it's trivially easy to win that argument, because in the case at hand it would be worse than useless --- it'd be flat-out wrong. puts() doesn't do the same thing as printf().
And why are you accusing the OP of not knowing what he is talking about?
Because he doesn't. While his first example is at least questionable, the other two are just wrong.
In item 2. his observation about strings constants not being folded is simply incorrect. One doesn't even have to look at generated code ... it doesn't even grow as much as it would have to if his complaint were true.
In item 3. his code doesn't do what he thinks it's doing --- there is no bit test in there.
Having actually looked at the examples, I can see that he is wrong about all of them. Obviously, I jumped to conclusions because I do believe that C51 isn't as good at optimization as it should be. The OP hasn't done his homework. Sorry for the noise.
You mean, isn't as good as it could be.
Yes, The compiler has removed the duplicate string i confirmed it. Very Sorry for the wrong statement.
But The other two are correct. The bit test and the printf to puts
Even though the printf function is a complete different & complicated one, when we use no var_arg ie when we use it only to print constant strings then it is completely equivalent to puts.Whether this is done by comiler or linker is not a quetion here. So there is no point in using bulky printf instead puts.
"3.Bit Test instructions are not used when i actually test for the bit
The processor's architecture allows for bit test instruction and the compiler did not use that single instruction but used three instructions instead.
Look again at your 'C' code - carefully!
Your 'C' code does not perform a bit test!
Your 'C' code is just using the standard 'C' exclusive-OR operator...
eli-project.sourceforge.net/.../c.html
docs.hp.com/.../ch05s21.html
www.tutorialspoint.com/.../c_operator_types.htm
The Above produces the following assembly code
ASSEMBLY LISTING OF GENERATED OBJECT CODE ; FUNCTION main (BEGIN) ; SOURCE LINE # 4 ; SOURCE LINE # 5 ; SOURCE LINE # 6 0000 7BFF MOV R3,#0FFH 0002 7A00 R MOV R2,#HIGH ?SC_0 0004 7900 R MOV R1,#LOW ?SC_0 ; SOURCE LINE # 7 ; SOURCE LINE # 8 ; SOURCE LINE # 9 ; SOURCE LINE # 10 ; SOURCE LINE # 11 ; SOURCE LINE # 12 ; SOURCE LINE # 13 ; SOURCE LINE # 14 ; SOURCE LINE # 15 ; SOURCE LINE # 16 ; SOURCE LINE # 17 ; SOURCE LINE # 18 ; SOURCE LINE # 19 ; SOURCE LINE # 20 ; SOURCE LINE # 21 ; SOURCE LINE # 22 0006 120000 R LCALL L?0002 ; SOURCE LINE # 23 ; SOURCE LINE # 24 ; SOURCE LINE # 25 ; SOURCE LINE # 26 ; SOURCE LINE # 27 ; SOURCE LINE # 28 ; SOURCE LINE # 29 ; SOURCE LINE # 30 ; SOURCE LINE # 31 ; SOURCE LINE # 32 ; SOURCE LINE # 33 ; SOURCE LINE # 34 ; SOURCE LINE # 35 ; SOURCE LINE # 36 ; SOURCE LINE # 37 ; SOURCE LINE # 38 0009 120000 R LCALL L?0002 000C 020000 E LJMP _puts ; SOURCE LINE # 39 000F L?0002: 000F 120000 E LCALL _puts 0012 7BFF MOV R3,#0FFH 0014 7A00 R MOV R2,#HIGH ?SC_0 0016 7900 R MOV R1,#LOW ?SC_0 0018 120000 E LCALL _puts 001B 7BFF MOV R3,#0FFH 001D 7A00 R MOV R2,#HIGH ?SC_0 001F 7900 R MOV R1,#LOW ?SC_0 0021 120000 E LCALL _puts 0024 7BFF MOV R3,#0FFH 0026 7A00 R MOV R2,#HIGH ?SC_0 0028 7900 R MOV R1,#LOW ?SC_0 002A 120000 E LCALL _puts 002D 7BFF MOV R3,#0FFH 002F 7A00 R MOV R2,#HIGH ?SC_0 C51 COMPILER V9.02 T 12/12/2010 06:18:02 PAGE 3 0031 7900 R MOV R1,#LOW ?SC_0 0033 120000 E LCALL _puts 0036 7BFF MOV R3,#0FFH 0038 7A00 R MOV R2,#HIGH ?SC_0 003A 7900 R MOV R1,#LOW ?SC_0 003C 120000 E LCALL _puts 003F 7BFF MOV R3,#0FFH 0041 7A00 R MOV R2,#HIGH ?SC_0 0043 7900 R MOV R1,#LOW ?SC_0 0045 120000 E LCALL _puts 0048 7BFF MOV R3,#0FFH 004A 7A00 R MOV R2,#HIGH ?SC_0 004C 7900 R MOV R1,#LOW ?SC_0 004E 120000 E LCALL _puts 0051 7BFF MOV R3,#0FFH 0053 7A00 R MOV R2,#HIGH ?SC_0 0055 7900 R MOV R1,#LOW ?SC_0 0057 120000 E LCALL _puts 005A 7BFF MOV R3,#0FFH 005C 7A00 R MOV R2,#HIGH ?SC_0 005E 7900 R MOV R1,#LOW ?SC_0 0060 120000 E LCALL _puts 0063 7BFF MOV R3,#0FFH 0065 7A00 R MOV R2,#HIGH ?SC_0 0067 7900 R MOV R1,#LOW ?SC_0 0069 120000 E LCALL _puts 006C 7BFF MOV R3,#0FFH 006E 7A00 R MOV R2,#HIGH ?SC_0 0070 7900 R MOV R1,#LOW ?SC_0 0072 120000 E LCALL _puts 0075 7BFF MOV R3,#0FFH 0077 7A00 R MOV R2,#HIGH ?SC_0 0079 7900 R MOV R1,#LOW ?SC_0 007B 120000 E LCALL _puts 007E 7BFF MOV R3,#0FFH 0080 7A00 R MOV R2,#HIGH ?SC_0 0082 7900 R MOV R1,#LOW ?SC_0 0084 120000 E LCALL _puts 0087 7BFF MOV R3,#0FFH 0089 7A00 R MOV R2,#HIGH ?SC_0 008B 7900 R MOV R1,#LOW ?SC_0 008D 120000 E LCALL _puts 0090 7BFF MOV R3,#0FFH 0092 7A00 R MOV R2,#HIGH ?SC_0 0094 7900 R MOV R1,#LOW ?SC_0 0096 120000 E LCALL _puts 0099 7BFF MOV R3,#0FFH 009B 7A00 R MOV R2,#HIGH ?SC_0 009D 7900 R MOV R1,#LOW ?SC_0 009F 22 RET ; FUNCTION main (END)
The optimiser should have used a counter and repeated the following block
MOV R3,#0FFH MOV R2,#HIGH ?SC_0 MOV R1,#LOW ?SC_0 LCALL _puts
I am not accusing,complaining or under estimating any one either at keil or in this forum I think only when we discuss we can improve.
If by anyway i hurted anybody's heart please forgive me!!
But the compiler knows i test for the bit...
when we use [printf] only to print constant strings then it is completely equivalent to puts.
So you believe --- but that belief is incorrect. Check your facts before you repeat incorrect statements like that. Read the specification of puts() again, carefully.
But your code doesn't specify any bit test instruction, so it would have been quite wrong for the compiler to use one. Like I said before, that '^' operator doesn't do what you think it does.
if the optimiser uses puts instead printf only when possible then we can reduce the size of the code and increase the speed both at the same time without causing any harm at all.
1.I did not mean to complain it was a mistake by the compiler.Here i am talking about improvement not mistake.
2.If it did replace the printf with puts where possible then it would improve the code efficiency and increase the speed.
3.If we turn off the optimiser then it was not neccessary to replace printf with puts.
4.The job of the optimiser to my knowledge is to reduce code and increase speed.That is what everybody would like.
5.Let me know what harm it will do if the optimser replaces (only when possible)printf("Testing"); with puts("Testing");.
5.Again the compiler knows that i am testing for the bit.And when the optimizer sees the code it should produce the smallest code possible.
6.Let me know the harm done when the optimiser uses bit test instruction instead of xor.
The advantage of using puts("This must call puts instead of printf"); instead of printf("This must call puts instead of printf");
1.Code size reduction 2.Increase in speed
Disadvantage NONE
Let me know if you know the disadvantage... puts over printf
The advantage of JNB over MOV,XRL and JZ
1.On instruction instead of three 2.Increase in speed.
Let me know if you know the disadvantage... JNB over MOV,XRL and JZ
It is only in the interest of improving the compiler
No, it does not - because the code that you have written does not test for a bit!
As already explained to you, the code you have written contains an expression using the ANSI Standard exclusive-OR operator.
Perhaps you are confusing the meaning of "bitwise", as used by the ANSI Standard, with the individual bit operations of the 8051...?
1) printf() does not do the same thing as puts() even if you send a constant not containing any % parameter expansions. Haven't you stil read up on puts() and seen what it does, _besides_ emitting the text string?
Well? I'm waiting. Have you read the documentation for puts yet? Still waiting...
2) You want the fastest code? Converting a sequence of calls put puts() with a loop isn't faster. Many optimizing compilers actually does the reverse. They do loop unrolling where they intentionally duplicate the code inside the loop to reduce the number of loop iterations - sometimes totally unrolling the loop so no loop operation remains.
3) my_byte XOR 1 inverts one bit in a byte, and then tests if the byte result is non-zero. That is not a single-bit operation that may use any bit instructins in the 8051 processor. The ^ may _only_ be used when declaring bit variables, since it is an overload of a standard C operator for XOR. And the standard C operator performs bit operations on full bytes/shorts/ints/long ints and not on a single bit.
Somehow, you have to switch from output mode into input mode. You must pick up the feedback you get in the forum, and not just run along further and further away on the wrong track.