瀏覽代碼

Added optimization: replace mul / div by shift if possible

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6874 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 年之前
父節點
當前提交
a3d159abe8
共有 5 個文件被更改,包括 50 次插入11 次删除
  1. 二進制
      source/Fox.Tool
  2. 21 0
      source/FoxAMDBackend.Mod
  3. 22 8
      source/FoxARMBackend.Mod
  4. 1 1
      source/FoxIntermediateBackend.Mod
  5. 6 2
      source/FoxInterpreter.Mod

二進制
source/Fox.Tool


+ 21 - 0
source/FoxAMDBackend.Mod

@@ -2118,7 +2118,16 @@ TYPE
 
 		PROCEDURE EmitMul(CONST instruction: IntermediateCode.Instruction);
 		VAR op1,op2,op3,temp: Assembler.Operand; ra,rd: Ticket;
+			value: HUGEINT; exp: LONGINT; iop3: IntermediateCode.Operand;
+			inst: IntermediateCode.Instruction;
 		BEGIN
+			IF IntermediateCode.IsConstantInteger(instruction.op3,value) & IntermediateBackend.PowerOf2(value,exp) THEN
+				IntermediateCode.InitImmediate(iop3, instruction.op3.type, exp);
+				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shl, instruction.op1, instruction.op2, iop3);
+				EmitShift(inst);
+				RETURN;
+			END;
+
 			ASSERT(~IsComplex(instruction.op1));
 			ASSERT(instruction.op1.type.form IN IntermediateCode.Integer);
 			IF (instruction.op1.type.sizeInBits = IntermediateCode.Bits8) THEN
@@ -2198,7 +2207,19 @@ TYPE
 			dividend,quotient,remainder,imm,target,memop: Assembler.Operand;
 			op1,op2,op3: Assembler.Operand; ra,rd: Ticket;
 			size: LONGINT;
+			value: HUGEINT; exp: LONGINT; iop3: IntermediateCode.Operand;
+			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);
+					IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shr, instruction.op1, instruction.op2, iop3);
+					EmitShift(inst);
+					RETURN;
+				END;
+			END;
+
 			(*
 			In general it must obviously hold that
 				a = (a div b) * b + a mod b and

+ 22 - 8
source/FoxARMBackend.Mod

@@ -635,7 +635,7 @@ TYPE
 		if not, the location of a runtime is returned **)
 		PROCEDURE Supported(CONST irInstruction: IntermediateCode.Instruction; VAR moduleName, procedureName: ARRAY OF CHAR): BOOLEAN;
 		VAR
-			result: BOOLEAN;
+			result: BOOLEAN; value: HUGEINT; exp: LONGINT;
 		BEGIN
 			CASE irInstruction.opcode OF
 			| IntermediateCode.add, IntermediateCode.sub, IntermediateCode.mul, IntermediateCode.abs, IntermediateCode.neg:
@@ -650,9 +650,7 @@ TYPE
 				result :=  backend.useFPU32 & IsSinglePrecisionFloat(irInstruction.op1) 
 							OR backend.useFPU64 & IsDoublePrecisionFloat(irInstruction.op1)
 							OR backend.useFPU64 & IsNonComplexInteger(irInstruction.op1);
-				(*
 				result := result OR IntermediateCode.IsConstantInteger(irInstruction.op3,value) & PowerOf2(value,exp)
-				*)
 
 			| IntermediateCode.conv:
 				IF IsInteger64(irInstruction.op1) & IsFloat(irInstruction.op2) THEN  (* ENTIERH: REAL/LONGREAL --> HUGEINT*)
@@ -665,10 +663,8 @@ TYPE
 									OR backend.useFPU64;
 				END;
 			| IntermediateCode.mod:
-				result := FALSE;
-				(*
 				result := IntermediateCode.IsConstantInteger(irInstruction.op3,value) & PowerOf2(value,exp)
-				*)
+				
 			| IntermediateCode.rol, IntermediateCode.ror:
 				result := ~IsComplex(irInstruction.op1)
 			ELSE
@@ -2202,8 +2198,16 @@ TYPE
 
 		PROCEDURE EmitMul(VAR irInstruction: IntermediateCode.Instruction);
 		VAR
-			destination, left, right: ARRAY 2 OF 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) & PowerOf2(value,exp) THEN
+				IntermediateCode.InitImmediate(op3, irInstruction.op3.type, exp);
+				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shl, irInstruction.op1, irInstruction.op2, op3);
+				EmitShiftOrRotation(inst);
+				RETURN;
+			END;
+
+		
 			IF IsSinglePrecisionFloat(irInstruction.op1) THEN
 				ASSERT(backend.useFPU32);
 				PrepareDoubleSourceOp(irInstruction, Low, destination[Low], left[Low], right[Low]);
@@ -2244,8 +2248,18 @@ TYPE
 
 		PROCEDURE EmitDiv(VAR irInstruction: IntermediateCode.Instruction);
 		VAR
-			destination, left, right, float, leftd, rightd, fpstatus: Operand;
+			destination, left, right, float, leftd, rightd, fpstatus: Operand; 
+			value: HUGEINT; exp: LONGINT; op3: IntermediateCode.Operand;
+			inst: IntermediateCode.Instruction;
 		BEGIN
+			IF IntermediateCode.IsConstantInteger(irInstruction.op3,value) & PowerOf2(value,exp) THEN
+				IntermediateCode.InitImmediate(op3, irInstruction.op3.type, exp);
+				IntermediateCode.InitInstruction(inst, -1, IntermediateCode.shr, irInstruction.op1, irInstruction.op2, op3);
+				EmitShiftOrRotation(inst);
+				RETURN;
+			END;
+
+		
 			IF IsSinglePrecisionFloat(irInstruction.op1) THEN
 				ASSERT(backend.useFPU32);
 				PrepareDoubleSourceOp(irInstruction, Low, destination, left, right);

+ 1 - 1
source/FoxIntermediateBackend.Mod

@@ -13557,7 +13557,7 @@ TYPE
 		END;
 	END IsIntegerConstant;
 
-	PROCEDURE PowerOf2(val: HUGEINT;  VAR exp: LONGINT): BOOLEAN;
+	PROCEDURE PowerOf2*(val: HUGEINT;  VAR exp: LONGINT): BOOLEAN;
 	BEGIN
 		IF val <= 0 THEN RETURN FALSE END;
 		exp := 0;

+ 6 - 2
source/FoxInterpreter.Mod

@@ -62,11 +62,15 @@ TYPE
 		BEGIN
 			IF (Token() = Scanner.ExclamationMark) THEN
 				statement := Cmd();
-				statements.AddStatement(statement);
+				IF statement # NIL THEN 
+					statements.AddStatement(statement);
+				END;
 				RETURN TRUE
 			ELSIF (Token() = Scanner.Questionmark) THEN
 				statement := Print();
-				statements.AddStatement(statement);
+				IF statement # NIL THEN 
+					statements.AddStatement(statement);
+				END;
 				RETURN TRUE
 			ELSE
 				RETURN Statement^(statements, outer);