From 854a6779a9f4ba8ee94a1e96759b0a024d150f67 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 19 Dec 2022 21:18:41 -0600 Subject: [PATCH] Generate even better code for constant returns. If the return value is just a numeric constant or static address, it can simply be loaded right before the RTL instruction, avoiding any data movement. This could actually be applied to a somewhat broader class of expressions, but for now it only applies to numeric or address constants, for which it is clearly correct. --- Gen.pas | 59 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/Gen.pas b/Gen.pas index 90884f5..9a554db 100644 --- a/Gen.pas +++ b/Gen.pas @@ -6975,29 +6975,37 @@ procedure GenTree {op: icptr}; size: integer; {localSize + parameterSize} lab1: integer; {label} valuePushed: boolean; {return value pushed on stack?} + evaluateAtEnd: boolean; {evaluate return val right before rtl?} begin {GenRetRev} size := localSize + parameterSize; + evaluateAtEnd := false; {calculate return value, if necessary} if op^.opcode = pc_rev then begin - valuePushed := namePushed or debugFlag or profileFlag - or ((parameterSize <> 0) and (size > 253)); - if valuePushed then - gLong.preference := onStack - else - gLong.preference := A_X; - GenTree(op^.left); - if op^.optype in [cgByte,cgUByte,cgWord,cgUWord] then begin - if valuePushed then - GenImplied(m_pha) - else - GenImplied(m_tay); + if op^.left^.opcode in [pc_ldc,pc_lca,pc_lao,pc_lad] then begin + evaluateAtEnd := true; + valuePushed := false; end {if} - else {if op^.optype in [cgLong,cgULong] then} begin - valuePushed := gLong.where = onStack; - if not valuePushed then - GenImplied(m_tay); + else begin + valuePushed := namePushed or debugFlag or profileFlag + or ((parameterSize <> 0) and (size > 253)); + if valuePushed then + gLong.preference := onStack + else + gLong.preference := A_X; + GenTree(op^.left); + if op^.optype in [cgByte,cgUByte,cgWord,cgUWord] then begin + if valuePushed then + GenImplied(m_pha) + else + GenImplied(m_tay); + end {if} + else {if op^.optype in [cgLong,cgULong] then} begin + valuePushed := gLong.where = onStack; + if not valuePushed then + GenImplied(m_tay); + end; {else} end; {else} end; @@ -7048,8 +7056,9 @@ procedure GenTree {op: icptr}; if op^.optype in [cgLong,cgULong] then GenImplied(m_plx); end {if} - else if size = 2 then - GenImplied(m_tya); + else if not evaluateAtEnd then + if size = 2 then + GenImplied(m_tya); end {if} else case op^.optype of {load the value to return} @@ -7121,14 +7130,24 @@ procedure GenTree {op: icptr}; {put return value in correct place} case op^.optype of cgByte,cgUByte,cgWord,cgUWord: begin - if size <> 2 then + if evaluateAtEnd then + GenTree(op^.left) + else if size <> 2 then GenImplied(m_tya); if toolParms then {save value on stack for tools} GenNative(m_sta_s, direct, returnSize+1, nil, 0); end; cgLong,cgULong,cgReal,cgDouble,cgComp,cgExtended: begin - if size <> 2 then + if evaluateAtEnd then begin + gLong.preference := A_X; + GenTree(op^.left); + if gLong.where = onStack then begin + GenImplied(m_pla); + GenImplied(m_plx); + end; {if} + end {if} + else if size <> 2 then GenImplied(m_tya); if toolParms then begin {save value on stack for tools} GenNative(m_sta_s, direct, returnSize+1, nil, 0);