OSDN Git Service

ART: Fix the simplifier for add/sub
authorSerguei Katkov <serguei.i.katkov@intel.com>
Wed, 5 Aug 2015 11:03:30 +0000 (17:03 +0600)
committerCalin Juravle <calin@google.com>
Thu, 6 Aug 2015 17:22:02 +0000 (18:22 +0100)
Instruction simplifier for add/sub should not proceed with floats
because that might cause the incorrect behavior with signed zero.

Change-Id: If0c9bf3931bcbf96b0814f8605a86997aea37145
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
compiler/optimizing/instruction_simplifier.cc
test/474-fp-sub-neg/expected.txt
test/474-fp-sub-neg/info.txt
test/474-fp-sub-neg/src/Main.java

index d391145..931a1c3 100644 (file)
@@ -438,9 +438,14 @@ void InstructionSimplifierVisitor::VisitAdd(HAdd* instruction) {
     //    ADD dst, src, 0
     // with
     //    src
-    instruction->ReplaceWith(input_other);
-    instruction->GetBlock()->RemoveInstruction(instruction);
-    return;
+    // Note that we cannot optimize `x + 0.0` to `x` for floating-point. When
+    // `x` is `-0.0`, the former expression yields `0.0`, while the later
+    // yields `-0.0`.
+    if (Primitive::IsIntegralType(instruction->GetType())) {
+      instruction->ReplaceWith(input_other);
+      instruction->GetBlock()->RemoveInstruction(instruction);
+      return;
+    }
   }
 
   HInstruction* left = instruction->GetLeft();
@@ -800,21 +805,24 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
   HInstruction* input_other = instruction->GetLeastConstantLeft();
 
+  Primitive::Type type = instruction->GetType();
+  if (Primitive::IsFloatingPointType(type)) {
+    return;
+  }
+
   if ((input_cst != nullptr) && input_cst->IsZero()) {
     // Replace code looking like
     //    SUB dst, src, 0
     // with
     //    src
+    // Note that we cannot optimize `x - 0.0` to `x` for floating-point. When
+    // `x` is `-0.0`, the former expression yields `0.0`, while the later
+    // yields `-0.0`.
     instruction->ReplaceWith(input_other);
     instruction->GetBlock()->RemoveInstruction(instruction);
     return;
   }
 
-  Primitive::Type type = instruction->GetType();
-  if (!Primitive::IsIntegralType(type)) {
-    return;
-  }
-
   HBasicBlock* block = instruction->GetBlock();
   ArenaAllocator* allocator = GetGraph()->GetArena();
 
index eced93f..82effdb 100644 (file)
@@ -1,5 +1,11 @@
 Regression check for optimizing simplify instruction pass.
+
 A pair (sub, neg) should not be transforemd to (sub) for
 fp calculation because we can lose the sign of zero for
 the following expression:
   - ( A - B ) != B - A ; if B == A
+
+Addition or subtraction with fp zero should not be eliminated
+because:
+  -0.0 + 0.0 = 0.0
+  -0.0 - -0.0 = 0.0
index e6bce67..c190e8e 100644 (file)
@@ -24,6 +24,8 @@ public class Main {
       }
 
       System.out.println(f);
+      System.out.println(f + 0f);
+      System.out.println(f - (-0f));
     }
 
     public static void doubleTest() {
@@ -35,6 +37,8 @@ public class Main {
       }
 
       System.out.println(d);
+      System.out.println(d + 0f);
+      System.out.println(d - (-0f));
     }
 
     public static void main(String[] args) {