[M3commit] CVS Update: cm3

Jay Krell jkrell at elego.de
Fri Feb 12 13:43:15 CET 2010


CVSROOT:	/usr/cvs
Changes by:	jkrell at birch.	10/02/12 13:43:15

Modified files:
	cm3/m3-sys/m3back/src/: Codex86.i3 Codex86.m3 M3x86.m3 

Log message:
	use inc/dec for atomic add/sub of 1 or -1
	
	before:
	lea esi,[_MM_Main+38h]
	mov ebx, 1
	lock inc    dword ptr [esi], ebx
	mov         dword ptr [_MM_Main+9Ch],esi
	
	after:
	lea         esi,[_MM_Main+38h]
	lock inc    dword ptr [esi]
	mov         dword ptr [_MM_Main+9Ch],esi
	
	ideal:
	lock inc    dword ptr [_MM_Main+38h]
	
	aha but I think I know why, will try for ideal
	
	I thought this was only going to save one byte:
	add foo,1
	vs.
	inc foo
	
	but we were loading 1 into a register as well
	(we could have gotten to add foo,1, but no point now)
	
	the unop changes not actually used here
	no unop is atomic, inc/dec are implemented separately
	I tried using the table based stuff but it is confusing
	
	diff:
	Index: Codex86.i3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/Codex86.i3,v
	retrieving revision 1.18
	diff -u -r1.18 Codex86.i3
	--- Codex86.i3	11 Feb 2010 14:59:51 -0000	1.18
	+++ Codex86.i3	12 Feb 2010 12:41:14 -0000
	@@ -60,8 +60,9 @@
	lock_compare_exchange (READONLY dest, src: Operand);
	pushOp (READONLY src: Operand);
	popOp (READONLY dest: Operand);
	-        decOp (READONLY op: Operand);
	-        unOp (op: Op; READONLY dest: Operand);
	+        decOp (READONLY op: Operand; locked := FALSE);
	+        incOp (READONLY op: Operand; locked := FALSE);
	+        unOp (op: Op; READONLY dest: Operand; locked := FALSE);
	mulOp (READONLY src: Operand);
	imulOp (READONLY dest, src: Operand);
	imulImm (READONLY dest, src: Operand; imm, imsize: INTEGER);
	Index: Codex86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/Codex86.m3,v
	retrieving revision 1.55
	diff -u -r1.55 Codex86.m3
	--- Codex86.m3	12 Feb 2010 11:19:26 -0000	1.55
	+++ Codex86.m3	12 Feb 2010 12:41:14 -0000
	@@ -92,6 +92,7 @@
	pushOp := pushOp;
	popOp := popOp;
	decOp := decOp;
	+        incOp := incOp;
	unOp := unOp;
	mulOp := mulOp;
	imulOp := imulOp;
	@@ -1019,26 +1020,49 @@
	END;
	END popOp;
	
	-PROCEDURE decOp (t: T; READONLY op: Operand) =
	+
	+PROCEDURE incOrDecOp (t: T; READONLY op: Operand; locked: BOOLEAN; incOrDec: [0..1]) =
	VAR ins: Instruction;
	+      name := ARRAY [0..1] OF TEXT{"INC", "DEC"}[incOrDec];
	BEGIN
	-    Mn(t, "DEC");  MnOp(t, op);
	+    ins.lock := locked;
	+    Mn(t, name);  MnOp(t, op);
	+
	<* ASSERT op.loc = OLoc.mem OR op.loc = OLoc.register *>
	-    IF op.loc = OLoc.register THEN
	-      ins.opcode := 16_48 + op.reg[0];
	+
	+    IF locked THEN
	+      ins.mrmpres := TRUE;
	+      ins.disp := 0;
	+      ins.dsize := 0;
	+      ins.modrm := 8 * incOrDec + op.reg[0];
	+      ins.opcode := 16_FF;
	+      writecode(t, ins);
	+    ELSIF op.loc = OLoc.register THEN
	+      ins.opcode := 16_40 + 8 * incOrDec + op.reg[0];
	writecode(t, ins);
	ELSE
	<* ASSERT op.loc = OLoc.mem AND CG_Bytes[op.mvar.mvar_type] = 4 *>
	-      build_modrm(t, op, t.opcode[1], ins);
	+      build_modrm(t, op, t.opcode[incOrDec], ins);
	ins.opcode := 16_FF;
	writecode(t, ins);
	log_global_var(t, op.mvar, -4);
	END
	+  END incOrDecOp;
	+
	+PROCEDURE incOp (t: T; READONLY op: Operand; locked := FALSE) =
	+  BEGIN
	+    incOrDecOp(t, op, locked, 0);
	+  END incOp;
	+
	+PROCEDURE decOp (t: T; READONLY op: Operand; locked := FALSE) =
	+  BEGIN
	+    incOrDecOp(t, op, locked, 1);
	END decOp;
	
	-PROCEDURE unOp1 (t: T; op: Op; READONLY dest: Operand) =
	+PROCEDURE unOp1 (t: T; op: Op; READONLY dest: Operand; locked := FALSE) =
	VAR ins: Instruction;
	BEGIN
	+    ins.lock := locked;
	ins.opcode := opcode[op].imm32;
	IF dest.loc = OLoc.mem THEN
	get_op_size(dest.mvar.mvar_type, ins);
	@@ -1057,11 +1081,14 @@
	END
	END unOp1;
	
	-PROCEDURE unOp (t: T; op: Op; READONLY dest: Operand) =
	+PROCEDURE unOp (t: T; op: Op; READONLY dest: Operand; locked := FALSE) =
	VAR destA: ARRAY OperandPart OF Operand;
	destSize := SplitOperand(dest, destA);
	BEGIN
	
	+    (* future: we could use cmpxchg loop *)
	+    <* ASSERT (destSize = 1) OR (NOT locked) *>
	+
	IF destSize = 2 AND (op IN SET OF Op{Op.oNEG, Op.oNOT}) THEN
	CASE op OF
	| Op.oNOT =>
	@@ -1079,7 +1106,7 @@
	<* ASSERT NOT Is64(destA[destSize - 1].optype) *>
	
	FOR i := 0 TO destSize - 1 DO
	-        unOp1(t, op, destA[i]);
	+        unOp1(t, op, destA[i], locked);
	END;
	END;
	END unOp;
	Index: M3x86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/M3x86.m3,v
	retrieving revision 1.110
	diff -u -r1.110 M3x86.m3
	--- M3x86.m3	12 Feb 2010 11:11:15 -0000	1.110
	+++ M3x86.m3	12 Feb 2010 12:41:15 -0000
	@@ -3004,7 +3004,8 @@
	u.vstack.newdest(u.cg.reg[EDI]);
	
	ELSE
	-      WITH stack0 = u.vstack.pos(0, "zero"), stop0 = u.vstack.op(stack0) DO
	+      WITH stack0 = u.vstack.pos(0, "zero"),
	+           stop0 = u.vstack.op(stack0) DO
	u.vstack.find(stack0, Force.anyreg, RegSet {}, TRUE);
	FOR i := 0 TO n - 1 DO
	u.cg.store_ind(Operand { loc := OLoc.imm, imm := TZero, optype := t },
	@@ -4297,15 +4298,16 @@
	CONST AtomicOpToOp = ARRAY AtomicOp OF Op { Op.oADD, Op.oSUB, Op.oOR, Op.oAND, Op.oXOR };
	CONST AtomicOpName = ARRAY AtomicOp OF TEXT { "add", "sub", "or", "and", "xor" };
	
	-PROCEDURE fetch_and_op (x: U; op: AtomicOp; t: MType; z: ZType;
	+PROCEDURE fetch_and_op (x: U; atomic_op: AtomicOp; t: MType; z: ZType;
	<*UNUSED*>order: MemoryOrder) =
	(* tmp := Mem [s1.A].t;
	Mem [s1.A].t := tmp op s0.u;
	s1.u := tmp op s0.u; pop *)
	+  VAR op := AtomicOpToOp[atomic_op];
	BEGIN
	IF x.debug THEN
	x.wr.Cmd   ("fetch_and_op");
	-      x.wr.OutT  (AtomicOpName[op]);
	+      x.wr.OutT  (AtomicOpName[atomic_op]);
	x.wr.TName (t);
	x.wr.TName (z);
	x.wr.NL    ();
	@@ -4318,7 +4320,35 @@
	RETURN;
	END;
	
	-    EVAL x.vstack.dobin(AtomicOpToOp[op], (*symmetric*) op # AtomicOp.Sub, (*overwritesdest*) TRUE, t, locked := TRUE);
	+    (* optimize add 1 => inc, add -1 => dec, sub 1 => dec, sub -1 => inc
	+     * to save a byte encoding the immediate value.
	+     * NOTE: We should do this for reg where t.reguse[reg].last_imm = 1 or -1 also.
	+     *)
	+
	+    WITH stack0 = x.vstack.pos(0, "fetch_and_op"),
	+         stack1 = x.vstack.pos(1, "fetch_and_op"),
	+         stop0 = x.vstack.op(stack0) DO
	+      IF op IN SET OF Op{Op.oADD, Op.oSUB} THEN
	+        IF stop0.loc = OLoc.imm THEN
	+          WITH imm = stop0.imm DO
	+            IF (TInt.EQ(imm, TInt.One) OR TInt.EQ(imm, TInt.MOne)) THEN
	+              x.vstack.unlock();
	+              x.vstack.find(stack1, Force.anyreg);
	+              IF (op = Op.oADD) = TInt.EQ(imm, TInt.One) THEN
	+                x.cg.incOp(x.vstack.op(stack1), locked := TRUE);
	+              ELSE
	+                x.cg.decOp(x.vstack.op(stack1), locked := TRUE);
	+              END;
	+              x.vstack.newdest(x.vstack.op(stack1));
	+              x.vstack.discard(1);
	+              RETURN;
	+            END;
	+          END;
	+        END;
	+      END;
	+    END;
	+
	+    EVAL x.vstack.dobin(op, (*symmetric*) (*op # AtomicOp.Sub*) FALSE, (*overwritesdest*) TRUE, t, locked := TRUE);
	
	END fetch_and_op;




More information about the M3commit mailing list