From 9b31e7f72acddaa9aa5e39175af4952e5acdaef1 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 10 Jul 2022 22:26:59 -0500 Subject: [PATCH] Improve code generation for comparisons. This converts comparisons like x > N (with constant N) to instead be evaluated as x >= N+1, since >= comparisons generate better code. This is possible as long as N is not the maximum value in the type, but in that case the comparison is always false. There are also a few other tweaks to the generated code in some cases. --- CGI.pas | 1 + Gen.pas | 143 +++++++++++++++++++---------------------------------- Native.pas | 4 +- 3 files changed, 54 insertions(+), 94 deletions(-) diff --git a/CGI.pas b/CGI.pas index b8f0efe..e049280 100644 --- a/CGI.pas +++ b/CGI.pas @@ -148,6 +148,7 @@ const m_ply = 122; m_plp = 40; m_rep = 194; + m_rol_a = $2A; m_ror_a = $6A; m_rtl = 107; m_rts = 96; diff --git a/Gen.pas b/Gen.pas index 85da9ff..34a17ff 100644 --- a/Gen.pas +++ b/Gen.pas @@ -1017,6 +1017,7 @@ var lab1,lab2,lab3,lab4: integer; {label numbers} num: integer; {constant to compare to} simple: boolean; {is this a simple case?} + alwaysFalse: boolean; {is the comparison always false?} procedure Switch; @@ -1067,36 +1068,38 @@ if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and (op^.right^.opcode = pc_ldc) then begin GenTree(op^.left); num := op^.right^.q; + {Convert x > N comparisons to x >= N+1, unless N is max value } + {(in which case x > N is always false). } + alwaysFalse := false; + if op^.opcode = pc_grt then begin + if ((op^.optype in [cgByte,cgWord]) and (num = 32767)) + or ((op^.optype in [cgUByte,cgUWord]) and (num = -1)) then + alwaysFalse := true + else begin + op^.opcode := pc_geq; + num := num+1; + end; {else} + end; {if} lab1 := GenLabel; if rOpcode = pc_fjp then begin - if op^.optype in [cgByte,cgWord] then begin + if alwaysFalse then + GenNative(m_brl, longrelative, lb, nil, 0) + else if op^.optype in [cgByte,cgWord] then begin if NeedsCondition(op^.left^.opcode) then GenImpliedForFlags(m_tax); - if (num >= 0) and (num < 4) then begin - if op^.opcode = pc_geq then begin - if num <> 0 then begin - lab2 := GenLabel; - GenNative(m_bmi, relative, lab2, nil, 0); - for i := 1 to num do - GenImplied(m_dea); - end; {if} - GenNative(m_bpl, relative, lab1, nil, 0); - if num <> 0 then - GenLab(lab2); - GenNative(m_brl, longrelative, lb, nil, 0); - GenLab(lab1); - end {if} - else {if opcode = pc_grt then} begin + if (num >= 0) and (num < 3) then begin + if num <> 0 then begin lab2 := GenLabel; GenNative(m_bmi, relative, lab2, nil, 0); - for i := 0 to num do + for i := 1 to num do GenImplied(m_dea); - GenNative(m_bpl, relative, lab1, nil, 0); + end; {if} + GenNative(m_bpl, relative, lab1, nil, 0); + if num <> 0 then GenLab(lab2); - GenNative(m_brl, longrelative, lb, nil, 0); - GenLab(lab1); - end; {else if} - end {if (num >= 0) and (num < 4)} + GenNative(m_brl, longrelative, lb, nil, 0); + GenLab(lab1); + end {if (num >= 0) and (num < 3)} else begin lab2 := GenLabel; if num > 0 then @@ -1104,14 +1107,7 @@ if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and else GenNative(m_bpl, relative, lab1, nil, 0); GenNative(m_cmp_imm, immediate, num, nil, 0); - if op^.opcode = pc_grt then begin - lab3 := GenLabel; - GenNative(m_beq, relative, lab3, nil, 0); - GenNative(m_bcs, relative, lab2, nil, 0); - GenLab(lab3); - end - else - GenNative(m_bcs, relative, lab2, nil, 0); + GenNative(m_bcs, relative, lab2, nil, 0); if num > 0 then begin GenLab(lab1); GenNative(m_brl, longrelative, lb, nil, 0); @@ -1124,49 +1120,30 @@ if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and end; {else if} end {if} else {if optype in [cgUByte,cgUWord] then} begin - GenNative(m_cmp_imm, immediate, num, nil, 0); - if op^.opcode = pc_grt then begin - lab2 := GenLabel; - GenNative(m_beq, relative, lab2, nil, 0); + if num <> 0 then begin + GenNative(m_cmp_imm, immediate, num, nil, 0); + GenNative(m_bcs, relative, lab1, nil, 0); + GenNative(m_brl, longrelative, lb, nil, 0); + GenLab(lab1); end; {if} - GenNative(m_bcs, relative, lab1, nil, 0); - if op^.opcode = pc_grt then - GenLab(lab2); - GenNative(m_brl, longrelative, lb, nil, 0); - GenLab(lab1); end; {else} end {if rOpcode = pc_fjp} else if rOpcode = pc_tjp then begin - if op^.optype in [cgByte,cgWord] then begin + if alwaysFalse then + {nothing to generate} + else if op^.optype in [cgByte,cgWord] then begin if NeedsCondition(op^.left^.opcode) then GenImpliedForFlags(m_tax); - if (num >= 0) and (num < 4) then begin - lab2 := GenLabel; - if op^.opcode = pc_geq then begin + if (num >= 0) and (num < 3) then begin + GenNative(m_bmi, relative, lab1, nil, 0); + if num > 0 then begin + for i := 1 to num do + GenImplied(m_dea); GenNative(m_bmi, relative, lab1, nil, 0); - if num > 0 then begin - for i := 1 to num do - GenImplied(m_dea); - GenNative(m_bmi, relative, lab2, nil, 0); - end; {if} - GenNative(m_brl, longrelative, lb, nil, 0); - end {if} - else {if op^.opcode = pc_grt then} begin - if num > 0 then begin - GenNative(m_bmi, relative, lab1, nil, 0); - for i := 0 to num do - GenImplied(m_dea); - GenNative(m_bmi, relative, lab2, nil, 0); - end {if} - else begin - GenNative(m_beq, relative, lab1, nil, 0); - GenNative(m_bmi, relative, lab2, nil, 0); - end; {else} - GenNative(m_brl, longrelative, lb, nil, 0); - end; {else} - GenLab(lab2); + end; {if} + GenNative(m_brl, longrelative, lb, nil, 0); GenLab(lab1); - end {if (num >= 0) and (num < 4)} + end {if (num >= 0) and (num < 3)} else begin lab2 := GenLabel; if num > 0 then @@ -1174,10 +1151,6 @@ if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and else GenNative(m_bpl, relative, lab1, nil, 0); GenNative(m_cmp_imm, immediate, num, nil, 0); - if op^.opcode = pc_grt then begin - lab3 := GenLabel; - GenNative(m_beq, relative, lab3, nil, 0); - end; {if} GenNative(m_bcc, relative, lab2, nil, 0); if num > 0 then begin GenNative(m_brl, longrelative, lb, nil, 0); @@ -1189,51 +1162,37 @@ if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and GenNative(m_brl, longrelative, lb, nil, 0); GenLab(lab2); end; {else} - if op^.opcode = pc_grt then - GenLab(lab3); end; {else} end {if} else {if optype in [cgUByte,cgUWord] then} begin - GenNative(m_cmp_imm, immediate, num, nil, 0); - GenNative(m_bcc, relative, lab1, nil, 0); - if op^.opcode = pc_grt then begin - lab2 := GenLabel; - GenNative(m_beq, relative, lab1, nil, 0); + if num <> 0 then begin + GenNative(m_cmp_imm, immediate, num, nil, 0); + GenNative(m_bcc, relative, lab1, nil, 0); end; {if} GenNative(m_brl, longrelative, lb, nil, 0); - if op^.opcode = pc_grt then - GenLab(lab2); - GenLab(lab1); + if num <> 0 then + GenLab(lab1); end; {else} end {if rOpcode = pc_tjp} + else if alwaysFalse then + GenNative(m_lda_imm, immediate, 0, nil, 0) else if op^.optype in [cgByte,cgWord] then begin lab2 := GenLabel; GenNative(m_ldx_imm, immediate, 1, nil, 0); GenImplied(m_sec); GenNative(m_sbc_imm, immediate, num, nil, 0); - if op^.opcode = pc_grt then begin - lab3 := GenLabel; - GenNative(m_beq, relative, lab3, nil, 0); - end; {if} GenNative(m_bvs, relative, lab1, nil, 0); GenNative(m_eor_imm, immediate, $8000, nil, 0); GenLab(lab1); GenNative(m_bmi, relative, lab2, nil, 0); - if op^.opcode = pc_grt then - GenLab(lab3); GenImplied(m_dex); GenLab(lab2); GenImplied(m_txa); end {else if} else begin - GenNative(m_ldx_imm, immediate, 0, nil, 0); GenNative(m_cmp_imm, immediate, num, nil, 0); - GenNative(m_bcc, relative, lab1, nil, 0); - if op^.opcode = pc_grt then - GenNative(m_beq, relative, lab1, nil, 0); - GenImplied(m_inx); - GenLab(lab1); - GenImplied(m_txa); + GenNative(m_lda_imm, immediate, 0, nil, 0); + GenImplied(m_rol_a); end; {else if} end {if (op^.optype in [cgByte,cgUByte,cgWord,cgUWord]) and (op^.right^.opcode = pc_ldc)} diff --git a/Native.pas b/Native.pas index 9cca90b..1f5652f 100644 --- a/Native.pas +++ b/Native.pas @@ -793,7 +793,7 @@ label 1,2,3; m_ina,m_lda_abs,m_lda_absx,m_lda_dir,m_lda_dirx,m_lda_imm,m_lda_indl, m_lda_indly,m_lda_long,m_lda_longx,m_lda_s,m_lsr_a,m_ora_abs,m_ora_dir, m_ora_dirX,m_ora_imm,m_ora_long,m_ora_longX,m_ora_s,m_ora_indl, - m_ora_indly,m_pla,m_ror_a,m_sbc_abs,m_sbc_dir,m_sbc_imm,m_sbc_s, + m_ora_indly,m_pla,m_rol_a,m_ror_a,m_sbc_abs,m_sbc_dir,m_sbc_imm,m_sbc_s, m_sbc_indl,m_sbc_indly,m_tax,m_tay,m_tcd,m_tdc,m_txa,m_tya]; end; {NZMatchA} @@ -805,7 +805,7 @@ case p_opcode of m_ora_dir,m_ora_dirX,m_ora_imm,m_ora_long,m_ora_longX,m_ora_s,m_pla, m_sbc_abs,m_sbc_dir,m_sbc_imm,m_sbc_s,m_tdc,m_tsc,m_adc_indl,m_adc_indly, m_and_indl,m_and_indly,m_ora_indl,m_ora_indly,m_sbc_indl,m_sbc_indly, - m_eor_indl,m_eor_indly,m_ror_a: + m_eor_indl,m_eor_indly,m_rol_a,m_ror_a: aRegister.condition := regUnknown; m_ldy_absX,m_ldy_dirX,m_ply: