changeset 2615:cbd54de385d3

Fix some issues with constant folding in CPU DSL
author Michael Pavone <pavone@retrodev.com>
date Mon, 17 Feb 2025 23:40:36 -0800
parents c5314c0779c2
children cbf5a01e429e
files cpu_dsl.py
diffstat 1 files changed, 56 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/cpu_dsl.py	Mon Feb 17 23:40:14 2025 -0800
+++ b/cpu_dsl.py	Mon Feb 17 23:40:36 2025 -0800
@@ -1297,18 +1297,53 @@
 		procParams = []
 		allParamsConst = flagUpdates is None and not prog.conditional
 		opDef = _opMap.get(self.op)
-		for param in self.params:
-			isDst = (not opDef is None) and len(procParams) in opDef.outOp
-			allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues
-			if isDst and self.op == 'xchg':
-				#xchg uses its regs as both source and destination
-				#we need to resolve as both so that disperse/coalesce flag stuff gets done
-				prog.resolveParam(param, parent, fieldVals, allowConst, False)
-			param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst)
-			
-			if (not type(param) is int) and len(procParams) != len(self.params) - 1:
+		if self.op == 'xchg':
+			#xchg uses its regs as both source and destination
+			#we need to resolve as both so that disperse/coalesce flag stuff gets done
+			#it also interacts weirdly with constant folding
+			a = prog.resolveParam(self.params[0], parent, fieldVals, True, False)
+			b = prog.resolveParam(self.params[1], parent, fieldVals, True, False)
+			dsta = prog.resolveParam(self.params[0], parent, fieldVals, False, True)
+			dstb = prog.resolveParam(self.params[1], parent, fieldVals, False, True)
+			dsta_nocontext = dsta[len("context->"):] if dsta.startswith('context->') else dsta
+			dstb_nocontext = dstb[len("context->"):] if dstb.startswith('context->') else dstb
+			if type(a) is int:
+				if type(b) is int:
+					#both params are constant, fold
+					parent.regValues[dsta_nocontext] = b
+					parent.regValues[dstb_nocontext] = a
+					if prog.isReg(dsta_nocontext):
+						output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None))
+					if prog.isReg(dstb_nocontext):
+						output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None))
+				else:
+					parent.regValues[dstb_nocontext] = a
+					del parent.regValues[dsta_nocontext]
+					output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None))
+					if prog.isReg(dstb_nocontext):
+						output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None))
+				prog.lastOp = self
+				return
+			elif type(b) is int:
+				parent.regValues[dsta_nocontext] = b
+				del parent.regValues[dstb_nocontext]
+				output.append(_opMap['mov'].generate(otype, prog, (a, dstb), (self.params[0], self.params[1]), None))
+				if prog.isReg(dsta_nocontext):
+					output.append(_opMap['mov'].generate(otype, prog, (b, dsta), (self.params[1], self.params[0]), None))
+				prog.lastOp = self
+				return
+			else:
+				procParams = [dsta, dstb]
 				allParamsConst = False
-			procParams.append(param)
+		else:			
+			for param in self.params:
+				isDst = (not opDef is None) and len(procParams) in opDef.outOp
+				allowConst = (self.op in prog.subroutines or not isDst) and param in parent.regValues
+				param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst)
+				
+				if (not type(param) is int) and len(procParams) != len(self.params) - 1:
+					allParamsConst = False
+				procParams.append(param)
 		if prog.needFlagCoalesce:
 			output.append(prog.flags.coalesceFlags(prog, otype))
 			prog.needFlagCoalesce = False
@@ -1355,7 +1390,14 @@
 						dst = prog.meta[dst]
 					if dst in parent.regValues:
 						del parent.regValues[dst]
-					
+				if self.op in ('ocall', 'ccall', 'pcall'):
+					#we called in to arbitrary C code, assume any reg could have changed
+					to_clear = []
+					for name in parent.regValues:
+						if prog.isReg(name):
+							to_clear.append(name)
+					for name in to_clear:
+						del parent.regValues[name]
 		elif self.op in prog.subroutines:
 			procParams = []
 			for param in self.params:
@@ -2138,6 +2180,8 @@
 						if isdst:
 							self.lastDst = param
 							self.lastSize = None
+						if allowConstant and maybeLocal in parent.regValues:
+							return parent.regValues[maybeLocal]
 						return maybeLocal
 				if param in fieldVals:
 					param = fieldVals[param]