Discussion:
Bypassing Promotions
(too old to reply)
bill rowe
2020-05-13 13:54:05 UTC
Permalink
I maintain a compiler for the 8 bit 1802 family. https://sites.google.com/site/lcc1802/

I built it mostly with assembly macros that line up with the internal operations. The code is readable(by me) and solid but tends to the clunky. One sore point with me is promotions. If I compare two unsigned chars the compiler feels obligated to promote both to ints and do a two byte compare so i end up with atrocities like:
; return a==b;
ld1 R11,'O',sp,(3+1)
zExt R11 ;CVUI2(INDIRU1(addr)): *widen unsigned char to signed int
ld1 R10,'O',sp,(2+1)
zExt R10 ;CVUI2(INDIRU1(addr)): *widen unsigned char to signed int
jneU2 R11,R10,L3; NE

I could recognize that pattern in the peephole optimizer but i could never be sure that intermediate results(R11 and R10) weren't being used further down.

It would be better to go upstream into the generation rules to catch it. I can see the symbolic output for the same statement as below but i'm not clear on how i could catch part of it. Has anyone done it? Could it be as simple as NEI2(CVUI2(reg),CVUI2(reg))?
; return a==b;
optimule.c:22.8:
4. ADDRLP2 a
3. INDIRU1 #4
2. CVUI2 #3 1
7. ADDRLP2 b
6. INDIRU1 #7
5. CVUI2 #6 1
1' NEI2 #2 #5 3
9. ADDRLP2 2
10. CNSTI2 1
8' ASGNI2 #9 #10 2 1
12. ADDRGP2 4
11' JUMPV #12
3:
15. ADDRLP2 2
16. CNSTI2 0
14' ASGNI2 #15 #16 2 1
4:
20. ADDRLP2 2
19. INDIRI2 #20
18' RETI2 #19
bill rowe
2020-05-13 14:55:50 UTC
Permalink
Update: That works quite well.
jacobnavia
2020-05-14 05:56:32 UTC
Permalink
Post by bill rowe
I maintain a compiler for the 8 bit 1802 family. https://sites.google.com/site/lcc1802/
; return a==b;
ld1 R11,'O',sp,(3+1)
zExt R11 ;CVUI2(INDIRU1(addr)): *widen unsigned char to signed int
ld1 R10,'O',sp,(2+1)
zExt R10 ;CVUI2(INDIRU1(addr)): *widen unsigned char to signed int
jneU2 R11,R10,L3; NE
I could recognize that pattern in the peephole optimizer but i could never be sure that intermediate results(R11 and R10) weren't being used further down.
It would be better to go upstream into the generation rules to catch it. I can see the symbolic output for the same statement as below but i'm not clear on how i could catch part of it. Has anyone done it? Could it be as simple as NEI2(CVUI2(reg),CVUI2(reg))?
; return a==b;
4. ADDRLP2 a
3. INDIRU1 #4
2. CVUI2 #3 1
7. ADDRLP2 b
6. INDIRU1 #7
5. CVUI2 #6 1
1' NEI2 #2 #5 3
9. ADDRLP2 2
10. CNSTI2 1
8' ASGNI2 #9 #10 2 1
12. ADDRGP2 4
11' JUMPV #12
15. ADDRLP2 2
16. CNSTI2 0
14' ASGNI2 #15 #16 2 1
20. ADDRLP2 2
19. INDIRI2 #20
18' RETI2 #19
I am using lcc 3.6, not lcc 4.2 but the underlying thing is the same. I
had the same problem in the x86. I wanted to compare directly two chars
instead of widening them to 32 bits and doing the comparison. I added
following rule:

stmt: NEI(CVCU(reg),CVCU(INDIRC(addr))) "\tcmpb\t%1,%0\
\tjne\t%a\n"

This way I compare directly without any widening.

Continue reading on narkive:
Loading...