Fix the division overflow.

Passing IntMath test.

Change-Id: I807858515a802f2efaa4802460e5f507eb944772
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 09b84ad..0ab8871 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -3284,12 +3284,8 @@
     return irb_.CreateMul(lhs, rhs);
 
   case kIntArithm_Div:
-    EmitGuard_DivZeroException(dex_pc, rhs, op_jty);
-    return irb_.CreateSDiv(lhs, rhs);
-
   case kIntArithm_Rem:
-    EmitGuard_DivZeroException(dex_pc, rhs, op_jty);
-    return irb_.CreateSRem(lhs, rhs);
+    return EmitIntDivRemResultComputation(dex_pc, lhs, rhs, arithm, op_jty);
 
   case kIntArithm_And:
     return irb_.CreateAnd(lhs, rhs);
@@ -3307,6 +3303,67 @@
 }
 
 
+llvm::Value*
+MethodCompiler::EmitIntDivRemResultComputation(uint32_t dex_pc,
+                                               llvm::Value* dividend,
+                                               llvm::Value* divisor,
+                                               IntArithmKind arithm,
+                                               JType op_jty) {
+  // Throw exception if the divisor is 0.
+  EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
+
+  // Check the special case: MININT / -1 = MININT
+  // That case will cause overflow, which is undefined behavior in llvm.
+  // So we check the divisor is -1 or not, if the divisor is -1, we do
+  // the special path to avoid undefined behavior.
+  llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
+  llvm::Value* zero = irb_.getJZero(op_jty);
+  llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
+  llvm::Value* result = irb_.CreateAlloca(op_type);
+
+  llvm::BasicBlock* eq_neg_one = CreateBasicBlockWithDexPC(dex_pc, "eq_neg_one");
+  llvm::BasicBlock* ne_neg_one = CreateBasicBlockWithDexPC(dex_pc, "ne_neg_one");
+  llvm::BasicBlock* neg_one_cont = CreateBasicBlockWithDexPC(dex_pc, "neg_one_cont");
+
+  llvm::Value* is_equal_neg_one = EmitConditionResult(divisor, neg_one, kCondBranch_EQ);
+  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one);
+
+  // If divisor == -1
+  irb_.SetInsertPoint(eq_neg_one);
+  llvm::Value* eq_result;
+  if (arithm == kIntArithm_Div) {
+    // We can just change from "dividend div -1" to "neg dividend".
+    // The sub don't care the sign/unsigned because of two's complement representation.
+    // And the behavior is what we want:
+    //  -(2^n)        (2^n)-1
+    //  MININT  < k <= MAXINT    ->     mul k -1  =  -k
+    //  MININT == k              ->     mul k -1  =   k
+    //
+    // LLVM use sub to represent 'neg'
+    eq_result = irb_.CreateSub(zero, dividend);
+  } else {
+    // Everything modulo -1 will be 0.
+    eq_result = zero;
+  }
+  irb_.CreateStore(eq_result, result);
+  irb_.CreateBr(neg_one_cont);
+
+  // If divisor != -1, just do the division.
+  irb_.SetInsertPoint(ne_neg_one);
+  llvm::Value* ne_result;
+  if (arithm == kIntArithm_Div) {
+    ne_result = irb_.CreateSDiv(dividend, divisor);
+  } else {
+    ne_result = irb_.CreateSRem(dividend, divisor);
+  }
+  irb_.CreateStore(ne_result, result);
+  irb_.CreateBr(neg_one_cont);
+
+  irb_.SetInsertPoint(neg_one_cont);
+  return irb_.CreateLoad(result);
+}
+
+
 void MethodCompiler::EmitInsn_IntShiftArithm(uint32_t dex_pc,
                                              Instruction const* insn,
                                              IntShiftArithmKind arithm,