OSDN Git Service

[optimizing] Improve 32 bit long shift by 1.
authorMark Mendell <mark.p.mendell@intel.com>
Wed, 6 May 2015 01:34:03 +0000 (21:34 -0400)
committerMark Mendell <mark.p.mendell@intel.com>
Mon, 11 May 2015 12:44:54 +0000 (08:44 -0400)
Also change FOO << 1 to FOO+FOO in the instruction simplifier.  This is
an architecture independent simplification, which helps 'long << 1' for
32 bit architectures.

Generate an add/adc for long << 1 in x86, in case something is generated
after the simplifier.

Add test cases for the simplification.

Change-Id: I0d512331ef13cc4ccf10c80f11c370a10ed02294
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/instruction_simplifier.cc
test/431-optimizing-arith-shifts/src/Main.java
test/458-checker-instruction-simplification/src/Main.java

index cfb8702..2848a48 100644 (file)
@@ -2830,7 +2830,11 @@ void InstructionCodeGeneratorX86::HandleShift(HBinaryOperation* op) {
 void InstructionCodeGeneratorX86::GenerateShlLong(const Location& loc, int shift) {
   Register low = loc.AsRegisterPairLow<Register>();
   Register high = loc.AsRegisterPairHigh<Register>();
-  if (shift == 32) {
+  if (shift == 1) {
+    // This is just an addition.
+    __ addl(low, low);
+    __ adcl(high, high);
+  } else if (shift == 32) {
     // Shift by 32 is easy. High gets low, and low gets 0.
     codegen_->EmitParallelMoves(
         loc.ToLow(),
index e79d4f4..46fad17 100644 (file)
@@ -137,13 +137,25 @@ void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
 
-  if ((input_cst != nullptr) && input_cst->IsZero()) {
-    // Replace code looking like
-    //    SHL dst, src, 0
-    // with
-    //    src
-    instruction->ReplaceWith(input_other);
-    instruction->GetBlock()->RemoveInstruction(instruction);
+  if (input_cst != nullptr) {
+    if (input_cst->IsZero()) {
+      // Replace code looking like
+      //    SHL dst, src, 0
+      // with
+      //    src
+      instruction->ReplaceWith(input_other);
+      instruction->GetBlock()->RemoveInstruction(instruction);
+    } else if (instruction->IsShl() && input_cst->IsOne()) {
+      // Replace Shl looking like
+      //    SHL dst, src, 1
+      // with
+      //    ADD dst, src, src
+      HAdd *add = new(GetGraph()->GetArena()) HAdd(instruction->GetType(),
+                                                   input_other,
+                                                   input_other);
+      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, add);
+      RecordSimplification();
+    }
   }
 }
 
index d8667c6..86422bd 100644 (file)
@@ -52,7 +52,7 @@ public class Main {
     expectEquals(Integer.MIN_VALUE, $opt$Shl(1073741824, 1));  // overflow
     expectEquals(1073741824, $opt$Shl(268435456, 2));
 
-   // othe nly 5 lower bits should be used for shifting (& 0x1f).
+    // Only the 5 lower bits should be used for shifting (& 0x1f).
     expectEquals(7, $opt$Shl(7, 32));  // 32 & 0x1f = 0
     expectEquals(14, $opt$Shl(7, 33));  // 33 & 0x1f = 1
     expectEquals(32, $opt$Shl(1, 101));  // 101 & 0x1f = 5
@@ -97,6 +97,13 @@ public class Main {
 
     expectEquals(Long.MIN_VALUE, $opt$Shl(7L, Long.MAX_VALUE));
     expectEquals(7L, $opt$Shl(7L, Long.MIN_VALUE));
+
+    // Exercise some special cases handled by backends/simplifier.
+    expectEquals(24L, $opt$ShlConst1(12L));
+    expectEquals(0x2345678900000000L, $opt$ShlConst32(0x123456789L));
+    expectEquals(0x2490249000000000L, $opt$ShlConst33(0x12481248L));
+    expectEquals(0x4920492000000000L, $opt$ShlConst34(0x12481248L));
+    expectEquals(0x9240924000000000L, $opt$ShlConst35(0x12481248L));
   }
 
   private static void shrInt() {
@@ -277,7 +284,7 @@ public class Main {
     return a >>> 2L;
   }
 
-    static int $opt$ShlConst0(int a) {
+  static int $opt$ShlConst0(int a) {
     return a << 0;
   }
 
@@ -301,5 +308,25 @@ public class Main {
     return a >>> 0L;
   }
 
+  static long $opt$ShlConst1(long a) {
+    return a << 1L;
+  }
+
+  static long $opt$ShlConst32(long a) {
+    return a << 32L;
+  }
+
+  static long $opt$ShlConst33(long a) {
+    return a << 33L;
+  }
+
+  static long $opt$ShlConst34(long a) {
+    return a << 34L;
+  }
+
+  static long $opt$ShlConst35(long a) {
+    return a << 35L;
+  }
+
 }
 
index 5d5a6b3..efb7b83 100644 (file)
@@ -223,6 +223,24 @@ public class Main {
     return arg << 0;
   }
 
+  // CHECK-START: int Main.Shl1(int) instruction_simplifier (before)
+  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
+  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
+  // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Arg]] [[Const1]] ]
+  // CHECK-DAG:                       Return [ [[Shl]] ]
+
+  // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
+  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Arg]] [[Arg]] ]
+  // CHECK-DAG:                       Return [ [[Add]] ]
+
+  // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+  // CHECK-NOT:                       Shl
+
+  public static int Shl1(int arg) {
+    return arg << 1;
+  }
+
   // CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
@@ -1060,5 +1078,6 @@ public class Main {
     assertDoubleEquals(Div2(150.0), 75.0);
     assertFloatEquals(DivMP25(100.0f), -400.0f);
     assertDoubleEquals(DivMP25(150.0), -600.0);
+    assertLongEquals(Shl1(100), 200);
   }
 }