Pārlūkot izejas kodu

Improved emission of MOD when power of two

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6877 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 gadi atpakaļ
vecāks
revīzija
f16b38f79e
3 mainītis faili ar 73 papildinājumiem un 31 dzēšanām
  1. 24 16
      source/FoxAMDBackend.Mod
  2. 23 7
      source/FoxARMBackend.Mod
  3. 26 8
      source/FoxTRMBackend.Mod

+ 24 - 16
source/FoxAMDBackend.Mod

@@ -1205,8 +1205,8 @@ TYPE
 					ELSE
 						EmitArithmetic3XMM(instruction, InstructionSet.opSUBSS, InstructionSet.opSUBSD)
 					END;
-				ELSE EmitArithmetic3(instruction,Low,InstructionSet.opSUB);
-					IF IsComplex(instruction.op1) THEN EmitArithmetic3(instruction, High, InstructionSet.opSBB) END;
+				ELSE EmitArithmetic3Part(instruction,Low,InstructionSet.opSUB);
+					IF IsComplex(instruction.op1) THEN EmitArithmetic3Part(instruction, High, InstructionSet.opSBB) END;
 				END;
 			|IntermediateCode.add:
 				IF IsFloat(instruction.op1) THEN
@@ -1215,21 +1215,18 @@ TYPE
 					ELSE
 						EmitArithmetic3XMM(instruction, InstructionSet.opADDSS, InstructionSet.opADDSD)
 					END;
-				ELSE EmitArithmetic3(instruction,Low,InstructionSet.opADD);
-					IF IsComplex(instruction.op1) THEN EmitArithmetic3(instruction, High, InstructionSet.opADC) END;
+				ELSE EmitArithmetic3Part(instruction,Low,InstructionSet.opADD);
+					IF IsComplex(instruction.op1) THEN EmitArithmetic3Part(instruction, High, InstructionSet.opADC) END;
 				END;
 			|IntermediateCode.and:
 				Assert(~IsFloat(instruction.op1),"operation not defined on float");
-				EmitArithmetic3(instruction,Low,InstructionSet.opAND);
-				IF IsComplex(instruction.op1) THEN EmitArithmetic3(instruction, High, InstructionSet.opAND) END;
+				EmitArithmetic3(instruction,InstructionSet.opAND);
 			|IntermediateCode.or:
 				Assert(~IsFloat(instruction.op1),"operation not defined on float");
-				EmitArithmetic3(instruction,Low,InstructionSet.opOR);
-				IF IsComplex(instruction.op1) THEN EmitArithmetic3(instruction, High, InstructionSet.opOR) END;
+				EmitArithmetic3(instruction,InstructionSet.opOR);
 			|IntermediateCode.xor:
 				Assert(~IsFloat(instruction.op1),"operation not defined on float");
-				EmitArithmetic3(instruction,Low,InstructionSet.opXOR);
-				IF IsComplex(instruction.op1) THEN EmitArithmetic3(instruction, High, InstructionSet.opXOR) END;
+				EmitArithmetic3(instruction,InstructionSet.opXOR);
 			|IntermediateCode.shl: EmitShift(instruction);
 			|IntermediateCode.shr: EmitShift(instruction);
 			|IntermediateCode.rol: EmitShift(instruction);
@@ -2056,19 +2053,25 @@ TYPE
 			END;
 		END FinishOp;
 
-		PROCEDURE EmitArithmetic3(CONST instruction: IntermediateCode.Instruction; part: LONGINT; opcode: LONGINT);
+		PROCEDURE EmitArithmetic3Part(CONST instruction: IntermediateCode.Instruction; part: LONGINT; opcode: LONGINT);
 		VAR left,right: Assembler.Operand; ticket: Ticket;
 		BEGIN
 			PrepareOp3(instruction, part, left,right,ticket);
 			emitter.Emit2(opcode,left,right);
 			FinishOp(instruction.op1,part,left,ticket);
+		END EmitArithmetic3Part;
+
+		PROCEDURE EmitArithmetic3(CONST instruction: IntermediateCode.Instruction; opcode: LONGINT);
+		BEGIN
+				EmitArithmetic3Part(instruction,Low,InstructionSet.opXOR);
+				IF IsComplex(instruction.op1) THEN EmitArithmetic3Part(instruction, High, InstructionSet.opXOR) END;
 		END EmitArithmetic3;
 
 		PROCEDURE EmitArithmetic3XMM(CONST instruction: IntermediateCode.Instruction; op32, op64: LONGINT);
 		VAR op: LONGINT;
 		BEGIN
 			IF instruction.op1.type.sizeInBits = 32 THEN op := op32 ELSE op := op64 END;
-			EmitArithmetic3(instruction, Low, op);
+			EmitArithmetic3Part(instruction, Low, op);
 		END EmitArithmetic3XMM;
 
 		PROCEDURE EmitArithmetic2(CONST instruction: IntermediateCode.Instruction; part: LONGINT; opcode: LONGINT);
@@ -2122,7 +2125,7 @@ TYPE
 			inst: IntermediateCode.Instruction;
 		BEGIN
 			IF IntermediateCode.IsConstantInteger(instruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
-				IntermediateCode.InitImmediate(iop3, instruction.op3.type, exp);
+				IntermediateCode.InitImmediate(iop3, IntermediateCode.uint32, exp);
 				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shl, instruction.op1, instruction.op2, iop3);
 				EmitShift(inst);
 				RETURN;
@@ -2211,12 +2214,17 @@ TYPE
 			inst: IntermediateCode.Instruction;
 
 		BEGIN
-			IF instruction.opcode = IntermediateCode.div THEN
-				IF IntermediateCode.IsConstantInteger(instruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
-					IntermediateCode.InitImmediate(iop3, instruction.op3.type, exp);
+			IF IntermediateCode.IsConstantInteger(instruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
+				IF instruction.opcode = IntermediateCode.div THEN					
+					IntermediateCode.InitImmediate(iop3, IntermediateCode.uint32, exp);
 					IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shr, instruction.op1, instruction.op2, iop3);
 					EmitShift(inst);
 					RETURN;
+				ELSE
+					IntermediateCode.InitImmediate(iop3, instruction.op3.type, value-1);
+					IntermediateCode.InitInstruction(inst, -1, IntermediateCode.and, instruction.op1, instruction.op2, iop3);
+					EmitArithmetic3(inst,InstructionSet.opAND);
+					RETURN;					
 				END;
 			END;
 

+ 23 - 7
source/FoxARMBackend.Mod

@@ -663,7 +663,7 @@ TYPE
 									OR backend.useFPU64;
 				END;
 			| IntermediateCode.mod:
-				result := IntermediateCode.IsConstantInteger(irInstruction.op3,value) & IntermediateBackend.PowerOf2(value,exp)
+				result :=  IntermediateCode.IsConstantInteger(irInstruction.op3,value) & IntermediateBackend.PowerOf2(value,exp)
 				
 			| IntermediateCode.rol, IntermediateCode.ror:
 				result := ~IsComplex(irInstruction.op1)
@@ -1534,7 +1534,7 @@ TYPE
 			| IntermediateCode.div: EmitDiv(irInstruction)
 			| IntermediateCode.mod: EmitMod(irInstruction)
 			| IntermediateCode.sub, IntermediateCode.add: EmitAddOrSub(irInstruction)
-			| IntermediateCode.and: EmitAnd(irInstruction, Low); IF IsComplex(irInstruction.op1) THEN EmitAnd(irInstruction, High) END
+			| IntermediateCode.and: EmitAnd(irInstruction);
 			| IntermediateCode.or: EmitOr(irInstruction, Low); IF IsComplex(irInstruction.op1) THEN EmitOr(irInstruction, High) END
 			| IntermediateCode.xor: EmitXor(irInstruction, Low); IF IsComplex(irInstruction.op1) THEN EmitXor(irInstruction, High) END
 			| IntermediateCode.shl: EmitShiftOrRotation(irInstruction)
@@ -2042,7 +2042,7 @@ TYPE
 			WriteBack(irInstruction.op1, part, destination)
 		END EmitNot;
 
-		PROCEDURE EmitAnd(VAR irInstruction: IntermediateCode.Instruction; part: LONGINT);
+		PROCEDURE EmitAndP(VAR irInstruction: IntermediateCode.Instruction; part: LONGINT);
 		VAR
 			dummy: BOOLEAN;
 			destination, left, right: Operand;
@@ -2050,6 +2050,12 @@ TYPE
 			PrepareDoubleSourceOpWithImmediate(irInstruction, part, destination, left, right, dummy);
 			Emit3(opAND, destination, left, right);
 			WriteBack(irInstruction.op1, part, destination)
+		END EmitAndP;
+
+		PROCEDURE EmitAnd(VAR irInstruction: IntermediateCode.Instruction);
+		BEGIN
+			EmitAndP(irInstruction, Low);
+			IF IsComplex(irInstruction.op1) THEN EmitAndP(irInstruction, High) END
 		END EmitAnd;
 
 		PROCEDURE EmitOr(VAR irInstruction: IntermediateCode.Instruction; part: LONGINT);
@@ -2198,10 +2204,11 @@ TYPE
 
 		PROCEDURE EmitMul(VAR irInstruction: IntermediateCode.Instruction);
 		VAR
-			destination, left, right: ARRAY 2 OF Operand; inst: IntermediateCode.Instruction; value: HUGEINT;exp: LONGINT; op3:IntermediateCode.Operand;
+			destination, left, right: ARRAY 2 OF Operand; inst: IntermediateCode.Instruction; 
+			value: HUGEINT;exp: LONGINT; op3:IntermediateCode.Operand;
 		BEGIN
 			IF IntermediateCode.IsConstantInteger(irInstruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
-				IntermediateCode.InitImmediate(op3, irInstruction.op3.type, exp);
+				IntermediateCode.InitImmediate(op3, IntermediateCode.uint32, exp);
 				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shl, irInstruction.op1, irInstruction.op2, op3);
 				EmitShiftOrRotation(inst);
 				RETURN;
@@ -2253,7 +2260,7 @@ TYPE
 			inst: IntermediateCode.Instruction;
 		BEGIN
 			IF IntermediateCode.IsConstantInteger(irInstruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
-				IntermediateCode.InitImmediate(op3, irInstruction.op3.type, exp);
+				IntermediateCode.InitImmediate(op3, IntermediateCode.uint32, exp);
 				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shr, irInstruction.op1, irInstruction.op2, op3);
 				EmitShiftOrRotation(inst);
 				RETURN;
@@ -2307,7 +2314,16 @@ TYPE
 		END EmitDiv;
 
 		PROCEDURE EmitMod(CONST irInstruction: IntermediateCode.Instruction);
-		BEGIN HALT(100) (* handled by a runtime call *)
+		VAR
+			value: HUGEINT;exp: LONGINT; op3:IntermediateCode.Operand; inst: IntermediateCode.Instruction;
+		BEGIN
+			IF IntermediateCode.IsConstantInteger(irInstruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
+				IntermediateCode.InitImmediate(op3, irInstruction.op3.type, value-1);
+				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.and, irInstruction.op1, irInstruction.op2, op3);
+				EmitAnd(inst);
+				RETURN;
+			END;
+			HALT(100) (* handled by a runtime call *)
 		END EmitMod;
 
 		PROCEDURE EmitAbs(VAR irInstruction: IntermediateCode.Instruction);

+ 26 - 8
source/FoxTRMBackend.Mod

@@ -402,7 +402,9 @@ TYPE
 				IF instr.op1.type.sizeInBits = IntermediateCode.Bits64 THEN
 					CASE instr.opcode OF
 					IntermediateCode.div: procedureName := "DivH";  RETURN FALSE
-					| IntermediateCode.mod: procedureName := "ModH"; RETURN FALSE
+					| IntermediateCode.mod: 
+						IF IntermediateCode.IsConstantInteger(instr.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN RETURN TRUE END;
+						procedureName := "ModH"; RETURN FALSE
 					| IntermediateCode.abs: procedureName := "AbsH"; RETURN FALSE;
 					| IntermediateCode.shl :
 						IF instr.op1.type.form = IntermediateCode.SignedInteger THEN
@@ -425,7 +427,9 @@ TYPE
 					IntermediateCode.div:	
 						IF IntermediateCode.IsConstantInteger(instr.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN RETURN TRUE 
 						ELSE procedureName := "DivL"; RETURN FALSE END;
-					| IntermediateCode.mod: procedureName := "ModL"; RETURN FALSE
+					| IntermediateCode.mod: 
+						IF IntermediateCode.IsConstantInteger(instr.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN RETURN TRUE END;
+						procedureName := "ModL"; RETURN FALSE
 					| IntermediateCode.mul:
 						IF (Global.NoMulCapability IN backend.capabilities) THEN  (*mul forbidden*)
 							IF IntermediateCode.IsConstantInteger(instr.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN RETURN TRUE 
@@ -684,10 +688,7 @@ TYPE
 					EmitAdd(instruction)
 				END
 			|IntermediateCode.and:
-				EmitAnd(instruction,Low);
-				IF IsComplex(instruction.op1) THEN
-					EmitAnd(instruction,High);
-				END;
+				EmitAnd(instruction);
 			|IntermediateCode.or:
 				EmitOr(instruction,Low);
 				IF IsComplex(instruction.op1) THEN
@@ -1513,19 +1514,36 @@ TYPE
 		END EmitDiv;
 
 		(* undefined for float and huegint, huegint version as library *)
-		PROCEDURE EmitMod(CONST instr: IntermediateCode.Instruction);
+		PROCEDURE EmitMod(CONST instruction: IntermediateCode.Instruction);
+		VAR
+			value: HUGEINT;exp: LONGINT; op3:IntermediateCode.Operand; inst: IntermediateCode.Instruction;
 		BEGIN
+			IF IntermediateCode.IsConstantInteger(instruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
+				IntermediateCode.InitImmediate(op3, instruction.op3.type, value-1);
+				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.and, instruction.op1, instruction.op2, op3);
+				EmitAnd(inst);
+				RETURN;
+			END;
 			HALT(100); (*! mod is not supported by hardware, must be runtime call -- cf. method Supported *)
 		END EmitMod;
 
-		PROCEDURE EmitAnd(VAR instruction: IntermediateCode.Instruction; part: LONGINT);
+		PROCEDURE EmitAndPart(VAR instruction: IntermediateCode.Instruction; part: LONGINT);
 		VAR left, right, dest: Operand; negate: BOOLEAN;
 		BEGIN
 			PrepareOp3(instruction,part,FALSE,negate,dest,left,right);
 			Emit2(opAND,left,right);
 			FinishOp(instruction.op1, part,dest, left)
+		END EmitAndPart;
+
+		PROCEDURE EmitAnd(VAR instruction: IntermediateCode.Instruction);
+		BEGIN
+				EmitAndPart(instruction,Low);
+				IF IsComplex(instruction.op1) THEN
+					EmitAndPart(instruction,High);
+				END;
 		END EmitAnd;
 
+
 		PROCEDURE EmitOr(VAR instruction: IntermediateCode.Instruction; part: LONGINT);
 		VAR left, right, dest: Operand; negate: BOOLEAN;
 		BEGIN