/* Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "instruction_simplifier_x86_shared.h"

#include "nodes_x86.h"

namespace art HIDDEN {

bool TryCombineAndNot(HAnd* instruction) {
  DataType::Type type = instruction->GetType();
  if (!DataType::IsIntOrLongType(type)) {
    return false;
  }
  // Replace code looking like
  //    Not tmp, y
  //    And dst, x, tmp
  //  with
  //    AndNot dst, x, y
  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  // Perform simplication only when either left or right
  // is Not. When both are Not, instruction should be simplified with
  // DeMorgan's Laws.
  if (left->IsNot() ^ right->IsNot()) {
    bool left_is_not = left->IsNot();
    HInstruction* other_ins = (left_is_not ? right : left);
    HNot* not_ins = (left_is_not ? left : right)->AsNot();
    // Only do the simplification if instruction has only one use
    // and thus can be safely removed.
    if (not_ins->HasOnlyOneNonEnvironmentUse()) {
      ArenaAllocator* arena = instruction->GetBlock()->GetGraph()->GetAllocator();
      HX86AndNot* and_not = new (arena) HX86AndNot(type,
                                                   not_ins->GetInput(),
                                                   other_ins,
                                                   instruction->GetDexPc());
      instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, and_not);
      DCHECK(!not_ins->HasUses());
      not_ins->GetBlock()->RemoveInstruction(not_ins);
      return true;
    }
  }
  return false;
}

bool TryGenerateResetLeastSetBit(HAnd* instruction) {
  DataType::Type type = instruction->GetType();
  if (!DataType::IsIntOrLongType(type)) {
    return false;
  }
  // Replace code looking like
  //    Add tmp, x, -1 or Sub tmp, x, 1
  //    And dest x, tmp
  //  with
  //    MaskOrResetLeastSetBit dest, x
  HInstruction* candidate = nullptr;
  HInstruction* other = nullptr;
  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  if (AreLeastSetBitInputs(left, right)) {
    candidate = left;
    other = right;
  } else if (AreLeastSetBitInputs(right, left)) {
    candidate = right;
    other = left;
  }
  if (candidate != nullptr && candidate->HasOnlyOneNonEnvironmentUse()) {
    ArenaAllocator* arena = instruction->GetBlock()->GetGraph()->GetAllocator();
    HX86MaskOrResetLeastSetBit* lsb = new (arena) HX86MaskOrResetLeastSetBit(
        type, HInstruction::kAnd, other, instruction->GetDexPc());
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, lsb);
    DCHECK(!candidate->HasUses());
    candidate->GetBlock()->RemoveInstruction(candidate);
    return true;
  }
  return false;
}

bool TryGenerateMaskUptoLeastSetBit(HXor* instruction) {
  DataType::Type type = instruction->GetType();
  if (!DataType::IsIntOrLongType(type)) {
    return false;
  }
  // Replace code looking like
  //    Add tmp, x, -1 or Sub tmp, x, 1
  //    Xor dest x, tmp
  //  with
  //    MaskOrResetLeastSetBit dest, x
  HInstruction* left = instruction->GetLeft();
  HInstruction* right = instruction->GetRight();
  HInstruction* other = nullptr;
  HInstruction* candidate = nullptr;
  if (AreLeastSetBitInputs(left, right)) {
    candidate = left;
    other = right;
  } else if (AreLeastSetBitInputs(right, left)) {
    candidate = right;
    other = left;
  }
  if (candidate != nullptr && candidate->HasOnlyOneNonEnvironmentUse()) {
    ArenaAllocator* arena = instruction->GetBlock()->GetGraph()->GetAllocator();
    HX86MaskOrResetLeastSetBit* lsb = new (arena) HX86MaskOrResetLeastSetBit(
        type, HInstruction::kXor, other, instruction->GetDexPc());
    instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, lsb);
    DCHECK(!candidate->HasUses());
    candidate->GetBlock()->RemoveInstruction(candidate);
    return true;
  }
  return false;
}

bool AreLeastSetBitInputs(HInstruction* to_test, HInstruction* other) {
  if (to_test->IsAdd()) {
    HAdd* add = to_test->AsAdd();
    HConstant* cst = add->GetConstantRight();
    return cst != nullptr && cst->IsMinusOne() && other == add->GetLeastConstantLeft();
  }
  if (to_test->IsSub()) {
    HSub* sub = to_test->AsSub();
    HConstant* cst = sub->GetConstantRight();
    return cst != nullptr && cst->IsOne() && other == sub->GetLeastConstantLeft();
  }
  return false;
}

}  // namespace art
