Please reply to this post on IBM-MAIN, where it was also posted!
Dear all,
A few days ago I posted the following to <
news://comp.lang.pl1>, addressed specifically to Peter Elderon:
Given part of a compiler listing (V5.2.2) below (and this is the code generated for the current source, which has been updated a bit over the weekend)
0038E8 D204 3AC0 BA0E 004142 |
0038EE D209 7000 6564 004142 |
0038F4 E350 DF14 0771 004142 |
0038FA D100 3AC7 BA12 004142 |
003900 D407 3AC0 2397 004142 |
003906 E310 D168 0258 004142 |
00390C E360 DEA0 0771 004143 |
003912 D207 3A98 3AC0 004142 |
003918 E380 D10C 0958 004143 |
00391E D707 3A90 3A90 004142 |
003924 FDF1 3A90 238D 004142 |
00392A E390 D110 0958 004143 |
003930 F87D EF60 3A90 004142 |
003936 D204 EF84 EF63 004142 |
00393C E300 DF14 0773 004142 |
003942 C00B 0000 000F 004142 |
003948 E300 DF14 0772 004142 |
00394E DE09 7000 5000 004142 |
003954 E300 DF1E 0795 004142 |
00395A 4000 1044 004142 |
00395E E310 D168 0258 004143 |
003964 D204 EF84 BA0E 004143 |
00396A F854 3AC8 BA0E 004143 |
003970 E350 D0F8 0958 004143 |
003976 D205 3A9A 3AC8 004143 |
00397C D709 3A90 3A90 004143 |
003982 4110 1047 004143 |
003986 E370 D108 0958 004143 |
00398C FDF1 3A90 238D 004143 |
003992 D201 EF7F 3A9E 004143 |
003998 D201 3ACE EF7F 004143 |
00399E F910 EF7F 238B 004143 |
0039A4 E3A0 D114 0958 004143 |
0039AA A7B4 001A 004143 |
0039AE D201 3AD1 3ACE 004143 |
0039B4 9200 3AD0 004143 |
0039B8 FA21 3AD0 238F 004143 |
0039BE F812 3AD4 3AD0 004143 |
0039C4 91F0 3AD4 004143 |
0039C8 A784 0008 004143 |
0039CC F010 3AD4 0001 004143 |
0039D2 F010 3AD4 0FFF 004143 |
0039D8 004143 |
0039D8 D201 EF7F 3AD4 004143 |
0039DE 004143 |
0039DE E320 DF0F 0771 004143 |
compiled with OPT(3) are the 004142 and 004143 actually really exclusively referring to statements 4142 and 4143? Because if they do...
And, maybe not surprisingly, only one person replied with a
"And the corresponding PL/I source is ?"
Note for what follows: PL/I has a truckload of builtin functions to work with dates and times, but none of them seem to cater for times in just minutes, as opposed to seconds or even micro-seconds.
The reason for asking the question? The two statements in question
min_max_line.t_max_hh = dtot.t_max / 60;
min_max_line.t_max_mm = mod(dtot.t_max, 60);
copy a time (in minutes, in packed format) to a print-line, in hh:mm format, which means splitting up said time into hh & mm by a division and a remainder, which, given that times can not be negative, can use PL/I's "MOD(ulo)" builtin function although obviously(!) that is not the best thing to do, as modulo and remainder may not have the same sign, given that modulo is defined as
"the smallest ***nonnegative*** value, R, such that (x - R)/y = n"
which immediately would suggest that IBM could/should add an optional third parameter to the "MOD" builtin function that can have the value 'U' to indicate that both other parameters should be treated as "U(nsigned)" (and no post-processing is required on the remainder to turn it into modulo), or add a new "UMOD" builtin function to do the same.
That's my first issue out of the way...
However, we're living AD 2020, Enterprise PL/I is an optimizing compiler, and so
it should make use of everything that the underlying hardware offers, and opening the PoP and the description of the "DP Divide Decimal" instruction tells
us that, emphasis (***) added:
"The first operand (the dividend) is divided by the second operand (the divisor). The resulting quotient ***and*** remainder are placed at the first- operand location. The operands and results are in the signed-packed decimal format."
Which is just what we need, and similar to what the x86 and AMD64 architectures do (RAX/EAX/AX/AH: quotient, RDX/EDX/DX/AH: remainder), so only one DP should be
required, but obviously that's something Enterprise PL/I misses, and, for what it's worth, I've got no clue as to what modern C compilers on the white-box platform might be doing, but this immediately suggests another new PL/I builtin function, "QUOTREM()", that might be invoked as
"quotient = QUOTREM(dividend, divisor], remainder]);",
where "remainder" is optional, although that's admittedly (more than) a bit silly.
That's issue two out of the way...
However, now we go for the real issue, the generated code, which seems to be a bit long-winded. Or rather more than that! A hell of a lot more!
I'm fortunate enough, don't ask, to still have access to the old
"5668-910 IBM OS PL/I OPTIMIZING COMPILER VER 2 REL 3 MOD 0"
and here's what it generates for those two statements. I've cut the relevant lines to 79 chars to hopefully avoid wrapping:
5668-910 IBM OS PL/I OPTIMIZING COMPILER VER 2 REL 3 MOD 0
- - - - - - - - - - - - - - - - - - - - - - - - - - -
2 MIN_MAX_INIT CHAR (121)
INIT ((' | | | | | | ' ||
'| | | : | : | : |')),
- - - - - - - - - - - - - - - - - - - - - - - - - - -
21 1 0 DCL 1 MIN_MAX_LINE BASED(LINE_PTR),
2 Z00069 CHAR (3),
2 MODE CHAR (4),
2 Z00070 CHAR (3),
2 #MIMA PIC 'zzz9',
2 Z00071 CHAR (3),
2 V_MAXR PIC 'zz9v.9',
2 Z00072 CHAR (3),
2 V_MINR PIC 'zz9v.9',
2 Z00073 CHAR (3),
2 V_AVG PIC 'zz9v.9',
2 Z00074 CHAR (3),
2 L_MAX PIC 'zzz9v.9',
2 Z00075 CHAR (3),
2 L_MIN PIC 'zzz9v.9',
2 Z00076 CHAR (3),
2 L_AVG PIC 'zzz9v.9',
2 Z00077 CHAR (3),
2 T_MAX_HH PIC 'z9',
2 Z00078 CHAR (1),
2 T_MAX_MM PIC '99',
2 Z00079 CHAR (3),
2 T_MIN_HH PIC 'z9',
2 Z00080 CHAR (1),
2 T_MIN_MM PIC '99',
2 Z00081 CHAR (3),
2 T_AVG_HH PIC 'z9',
2 Z00082 CHAR (1),
2 T_AVG_MM PIC '99';
- - - - - - - - - - - - - - - - - - - - - - - - - - -
27 1 0 DCL 1 LIFT_WORK,
- - - - - - - - - - - - - - - - - - - - - - - - - - -
2 LINE_PTR PTR INIT (ADDR(LINE)),
- - - - - - - - - - - - - - - - - - - - - - - - - - -
2 LINE CHAR (121) INIT ((121)' '),
- - - - - - - - - - - - - - - - - - - - - - - - - - -
369 1 0 LINE = MIN_MAX_INIT;
370 1 0 MIN_MAX_LINE.MODE = 'Tot ';
- - - - - - - - - - - - - - - - - - - - - - - - - - -
378 1 0 MIN_MAX_LINE.T_MAX_HH = DTOT.T_MAX / 60;
379 1 0 MIN_MAX_LINE.T_MAX_MM = MOD(DTOT.T_MAX, 60);
- - - - - - - - - - - - - - - - - - - - - - - - - - - * STATEMENT NUMBER 369 (1)
002D68 58 B0 3 818 L 11,2072(0,3)
002D6C 58 70 D 0CC L 7,204(0,13)
002D70 D2 78 7 91B B 794 MVC LIFT_WORK.LINE(121),LIFT_STATIC.MIN_MAX_INIT (a wrapped line, sorry)
* STATEMENT NUMBER 370 (1)
002D76 58 F0 9 2C8 L 15,LIFT_WORK.LINE_PTR
002D7A 58 E0 3 810 L 14,2064(0,3)
002D7E D2 03 F 003 E A49 MVC MIN_MAX_LINE.MODE(4),2633(14)
- - - - - - - - - - - - - - - - - - - - - - - - - - - * STATEMENT NUMBER 378 (1)
002E94 D7 09 D 098 D 098 XC WKSP.1+32(10),WKSP.1+32
002E9A D2 04 D 09A 7 B2E MVC WKSP.1+34(5),LIFT_WORK.DTOT.T_MAX 002EA0 94 F0 D 09E NI WKSP.1+38,X'F0'
002EA4 D1 00 D 0A1 7 B32 MVN WKSP.1+41(1),LIFT_WORK.DTOT.T_MAX+4 002EAA FD 91 D 098 E 9E5 DP WKSP.1+32(10),2533(2,14)
002EB0 D2 07 4 308 D 098 MVC 776(8,4),WKSP.1+32
002EB6 D2 03 4 310 8 130 MVC 784(4,4),304(8)
002EBC DE 03 4 310 4 30B ED 784(4,4),779(4)
002EC2 D2 01 F 044 4 312 MVC MIN_MAX_LINE.T_MAX_HH(2),786(4)
* STATEMENT NUMBER 379 (1)
002EC8 D2 01 4 308 E 9E5 MVC 776(2,4),2533(14)
002ECE F8 94 D 098 7 B2E ZAP WKSP.1+32(10),LIFT_WORK.DTOT.T_MAX(5) 002ED4 FD 91 D 098 4 308 DP WKSP.1+32(10),776(2,4)
002EDA D2 01 4 30A D 0A0 MVC 778(2,4),WKSP.1+40
002EE0 50 F0 4 390 ST 15,912(0,4)
002EE4 F9 10 4 30A E 9B1 CP 778(2,4),2481(1,14)
002EEA 47 B0 2 754 BNL CL.3727
002EEE 94 FE 4 309 NI 777(4),X'FE'
002EF2 FA 11 4 30A 4 308 AP 778(2,4),776(2,4)
002EF8 CL.3727 EQU *
002EF8 D2 01 4 308 4 30A MVC 776(2,4),778(4)
002EFE 58 E0 4 390 L 14,912(0,4)
002F02 F3 11 E 047 4 308 UNPK MIN_MAX_LINE.T_MAX_MM(2),776(2,4) 002F08 96 F0 E 048 OI MIN_MAX_LINE.T_MAX_MM+1,X'F0'
Note that the listing is post-processed to merge the originally split the generated assembler and to add execution counts to the "* STATEMENT NUMBER" lines.
Count? 22 instructions for the two statements, the destination (R15) is loaded once in statement 369, for a total of 23 instructions, or let's just go for the lot, 28 assembler statements for the four PL/I statements.
Now sit back and look at what a even whiter and shinier compiler AD 2018 produces, and yes, the listing has been heavily white-space edited to avoid wrapping:
5655-PL5 IBM(R) Enterprise PL/I for z/OS V5.R2.M2 (Built:20180530)
- - - - - - - - - - - - - - - - - - - - - - - - - -
1178.0 2 min_max_init char (121)
1179.0 init ((' | | | | | | ' ||
1180.0 '| | | : | : | : |')),
- - - - - - - - - - - - - - - - - - - - - - - - -
2135.0 21 1 dcl 1 min_max_line based(line_ptr),
2136.0 2 * char (3),
2137.0 2 mode char (4),
2138.0 2 * char (3),
2139.0 2 #mima pic 'zzz9',
2140.0 2 * char (3),
2141.0 2 v_maxr pic 'zz9v.9',
2142.0 2 * char (3),
2143.0 2 v_minr pic 'zz9v.9',
2144.0 2 * char (3),
2145.0 2 v_avg pic 'zz9v.9',
2146.0 2 * char (3),
2147.0 2 l_max pic 'zzz9v.9',
2148.0 2 * char (3),
2149.0 2 l_min pic 'zzz9v.9',
2150.0 2 * char (3),
2151.0 2 l_avg pic 'zzz9v.9',
2152.0 2 * char (3),
2153.0 2 t_max_hh pic 'z9',
2154.0 2 * char (1),
2155.0 2 t_max_mm pic '99',
2156.0 2 * char (3),
2157.0 2 t_min_hh pic 'z9',
2158.0 2 * char (1),
2159.0 2 t_min_mm pic '99',
2160.0 2 * char (3),
2161.0 2 t_avg_hh pic 'z9',
2162.0 2 * char (1),
2163.0 2 t_avg_mm pic '99';
- - - - - - - - - - - - - - - - - - - - - - - - -
2256.0 27 1 dcl 1 lift_work,
- - - - - - - - - - - - - - - - - - - - - - - - -
2468.0 2 line_ptr ptr init (addr(line)),
- - - - - - - - - - - - - - - - - - - - - - - - -
2532.0 2 line char (121) init ((121)' '),
- - - - - - - - - - - - - - - - - - - - - - - - -
4128.0 405 1 line = min_max_init;
4129.0 406 1 min_max_line.mode = 'Tot ';
- - - - - - - - - - - - - - - - - - - - - - - - -
4142.0 414 1 min_max_line.t_max_hh = dtot.t_max / 60;
4143.0 415 1 min_max_line.t_max_mm = mod(dtot.t_max, 60);
- - - - - - - - - - - - - - - - - - - - - - - - - - 0035D0 58E0 4000 4128 L r14,=A(***LIFT2)(,r4,0)
0035D4 C0B0 0001 B58E 4129 LARL r11,F'112014'
0035DA E3F0 D7BB 0471 4128 LAY r15,LINE(,r13,18363)
- - - - - - - - - - - - - - - - - - - - - - - - - - 0035E6 E310 E4CC 0671 4128 LAY r1,MIN_MAX_INIT(,r14,25804)
0035EC E3E0 D168 0258 4129 LY r14,<a1:d8552:l4>(,r13,8552)
0035F2 D278 F000 1000 4128 MVC LINE(121,r15,0),MIN_MAX_INIT(r1,0)
0035F8 5800 B558 4129 L r0,<s3864:d1368:l4>(,r11,1368)
- - - - - - - - - - - - - - - - - - - - - - - - - - 003602 5000 E003 4129 ST r0,_shadow17(,r14,3)
- - - - - - - - - - - - - - - - - - - - - - - - - - 003802 D201 3AD8 238D 4142
MVC #pd55727_1(2,r3,2776),+CONSTANT_AREA(r2,909)
- - - - - - - - - - - - - - - - - - - - - - - - - - 00382A E370 DF1C 0771 4142 LAY r7,_temp40(,r13,32540)
- - - - - - - - - - - - - - - - - - - - - - - - - - 0038D0 D200 3AD6 238B 4143
MVC #pd55702_1(1,r3,2774),+CONSTANT_AREA(r2,907)
- - - - - - - - - - - - - - - - - - - - - - - - - - 0038E8 D204 3AC0 BA0E 4142 MVC #pd45865_1(5,r3,2752),T_MAX(r11,2574) 0038EE D209 7000 6564 4142 MVC _temp40(10,r7,0),' .........'(r6,1380) 0038F4 E350 DF14 0771 4142 LAY r5,_temp39(,r13,32532)
0038FA D100 3AC7 BA12 4142 MVN #pd45865_1(1,r3,2759),T_MAX(r11,2578) 003900 D407 3AC0 2397 4142
NC #pd45865_1(8,r3,2752),+CONSTANT_AREA(r2,919) 003906 E310 D168 0258 4142 LY r1,<a1:d8552:l4>(,r13,8552)
00390C E360 DEA0 0771 4143 LAY r6,_temp25(,r13,32416)
003912 D207 3A98 3AC0 4142 MVC #pd46742_1(8,r3,2712),#pd45865_1(r3,2752) 003918 E380 D10C 0958 4143 LY r8,#SPILL32(,r13,37132)
00391E D707 3A90 3A90 4142 XC #pd46742_1(8,r3,2704),#pd46742_1(r3,2704) 003924 FDF1 3A90 238D 4142
DP #pd46742_1(16,r3,2704),+CONSTANT_AREA(2,r2,909) 00392A E390 D110 0958 4143 LY r9,#SPILL33(,r13,37136)
003930 F87D EF60 3A90 4142 ZAP _temp33(8,r14,3936),#pd46742_1(14,r3,2704) 003936 D204 EF84 EF63 4142 MVC _temp39(5,r14,3972),_temp33(r14,3939) 00393C E300 DF14 0773 4142 ICY r0,<a1:d32532:l1>(,r13,32532)
003942 C00B 0000 000F 4142 NILF r0,F'15'
003948 E300 DF14 0772 4142 STCY r0,<a1:d32532:l1>(,r13,32532)
00394E DE09 7000 5000 4142 ED _temp40(10,r7,0),_temp39(r5,0)
003954 E300 DF1E 0795 4142 LLH r0,<a1:d32542:l2>(,r13,32542)
00395A 4000 1044 4142 STH r0,_shadow20(,r1,68)
00395E E310 D168 0258 4143 LY r1,<a1:d8552:l4>(,r13,8552)
003964 D204 EF84 BA0E 4143 MVC _temp39(5,r14,3972),T_MAX(r11,2574)
00396A F854 3AC8 BA0E 4143 ZAP #pd45874_1(6,r3,2760),T_MAX(5,r11,2574) 003970 E350 D0F8 0958 4143 LY r5,#SPILL27(,r13,37112)
003976 D205 3A9A 3AC8 4143 MVC #pd46742_1(6,r3,2714),#pd45874_1(r3,2760) 00397C D709 3A90 3A90 4143 XC #pd46742_1(10,r3,2704),#pd46742_1(r3,2704) 003982 4110 1047 4143 LA r1,#AddressShadow(,r1,71)
003986 E370 D108 0958 4143 LY r7,#SPILL31(,r13,37128)
00398C FDF1 3A90 238D 4143
DP #pd46742_1(16,r3,2704),+CONSTANT_AREA(2,r2,909) 003992 D201 EF7F 3A9E 4143 MVC _temp38(2,r14,3967),#pd46742_1(r3,2718) 003998 D201 3ACE EF7F 4143 MVC #pd1753_1(2,r3,2766),_temp38(r14,3967) 00399E F910 EF7F 238B 4143 CP _temp38(2,r14,3967),+CONSTANT_AREA(1,r2,907)
0039A4 E3A0 D114 0958 4143 LY r10,#SPILL34(,r13,37140)
0039AA A7B4 001A 4143 JNL @1L599
0039AE D201 3AD1 3ACE 4143 MVC #pd1756_1(2,r3,2769),#pd1753_1(r3,2766) 0039B4 9200 3AD0 4143 MVI #pd1756_1(r3,2768),0
0039B8 FA21 3AD0 238F 4143
AP #pd1756_1(3,r3,2768),+CONSTANT_AREA(2,r2,911) 0039BE F812 3AD4 3AD0 4143 ZAP #pd1757_1(2,r3,2772),#pd1756_1(3,r3,2768) 0039C4 91F0 3AD4 4143 TM #pd1757_1(r3,2772),240
0039C8 A784 0008 4143 JE @1L18801
0039CC F010 3AD4 0001 4143 SRP #pd1757_1(2,r3,2772),1,0
0039D2 F010 3AD4 0FFF 4143 SRP #pd1757_1(2,r3,2772),-1,0
0039D8 4143 @1L18801 DS 0H
0039D8 D201 EF7F 3AD4 4143 MVC _temp38(2,r14,3967),#pd1757_1(r3,2772) 0039DE 4143 @1L599 DS 0H
0039DE E320 DF0F 0771 4143 LAY r2,_temp38(,r13,32527)
- - - - - - - - - --- -- - - - - - - - - - - - - - - 0039F0 C0E0 0001 B380 4143 LARLr14,F'111488'
0039F6 E330 DF88 0771 4143 LAY r3,#PDTEMPS1(,r13,32648)
0039FC F311 1000 2000 4143 UNPK_shadow20(2,r1,0),_temp38(2,r2,0)
003A02 96F0 1001 4143 OI _shadow20(r1,1),240
- - - - - - - - - --- -- - - - - - - - - - - - - - - 003A12 4120 EFF1 4143 LA r2,+CONSTANT_AREA(,r14,4081)
This time I count 60(!) assembler instructions for the four PL/I statements, and
if you start deleting statements that occur in both listings, don't worry, I've done it for you, there are six statements in the "VER 2 REL 3 MOD 0" listing that do not match 38(!) statements in the "V5.R2.M2", or maybe 5/37 if I'm allowed to equate "BNL" with "JNL"
Maybe someone can explain what's happening?
For what it's worth, few years ago I gate-crashed a GSE PL/I + COBOL meeting, in
Eisenach (Germany) and there one of the IBM'ers (not Peter Elderon!) told me that IBM compilers were the pinnacle, and years ahead of anything Open Source.
In fact I've read this, cannot find the source right now, about the old OS Compiler, and that is indeed a one of a kind, capable of still generating working code from code that comes close to letting a monkey use a terminal!
However, given that people pay a substantial amount of money to use Enterprise PL/I, I think that compiler could do with a bit more TLC...
Robert
--
Robert AH Prins
robert.ah.prins(a)gmail.com
The hitchhiking grandfather -
https://prino.neocities.org/indez.html
Some REXX code for use on z/OS -
https://prino.neocities.org/zOS/zOS-Tools.html
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)