Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
     18 #define ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
     19 
     20 // This `#include` should never be used by compilation, as this file (`nodes_shared.h`) is included
     21 // in `nodes.h`. However it helps editing tools (e.g. YouCompleteMe) by giving them better context
     22 // (defining `HInstruction` and co).
     23 #include "nodes.h"
     24 
     25 namespace art {
     26 
     27 class HMultiplyAccumulate FINAL : public HExpression<3> {
     28  public:
     29   HMultiplyAccumulate(Primitive::Type type,
     30                       InstructionKind op,
     31                       HInstruction* accumulator,
     32                       HInstruction* mul_left,
     33                       HInstruction* mul_right,
     34                       uint32_t dex_pc = kNoDexPc)
     35       : HExpression(type, SideEffects::None(), dex_pc), op_kind_(op) {
     36     SetRawInputAt(kInputAccumulatorIndex, accumulator);
     37     SetRawInputAt(kInputMulLeftIndex, mul_left);
     38     SetRawInputAt(kInputMulRightIndex, mul_right);
     39   }
     40 
     41   static constexpr int kInputAccumulatorIndex = 0;
     42   static constexpr int kInputMulLeftIndex = 1;
     43   static constexpr int kInputMulRightIndex = 2;
     44 
     45   bool CanBeMoved() const OVERRIDE { return true; }
     46   bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
     47     return op_kind_ == other->AsMultiplyAccumulate()->op_kind_;
     48   }
     49 
     50   InstructionKind GetOpKind() const { return op_kind_; }
     51 
     52   DECLARE_INSTRUCTION(MultiplyAccumulate);
     53 
     54  private:
     55   // Indicates if this is a MADD or MSUB.
     56   const InstructionKind op_kind_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(HMultiplyAccumulate);
     59 };
     60 
     61 class HBitwiseNegatedRight FINAL : public HBinaryOperation {
     62  public:
     63   HBitwiseNegatedRight(Primitive::Type result_type,
     64                             InstructionKind op,
     65                             HInstruction* left,
     66                             HInstruction* right,
     67                             uint32_t dex_pc = kNoDexPc)
     68     : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc),
     69       op_kind_(op) {
     70     DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
     71   }
     72 
     73   template <typename T, typename U>
     74   auto Compute(T x, U y) const -> decltype(x & ~y) {
     75     static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
     76                   std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
     77                   "Inconsistent negated bitwise types");
     78     switch (op_kind_) {
     79       case HInstruction::kAnd:
     80         return x & ~y;
     81       case HInstruction::kOr:
     82         return x | ~y;
     83       case HInstruction::kXor:
     84         return x ^ ~y;
     85       default:
     86         LOG(FATAL) << "Unreachable";
     87         UNREACHABLE();
     88     }
     89   }
     90 
     91   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
     92     return GetBlock()->GetGraph()->GetIntConstant(
     93         Compute(x->GetValue(), y->GetValue()), GetDexPc());
     94   }
     95   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
     96     return GetBlock()->GetGraph()->GetLongConstant(
     97         Compute(x->GetValue(), y->GetValue()), GetDexPc());
     98   }
     99   HConstant* Evaluate(HFloatConstant* x ATTRIBUTE_UNUSED,
    100                       HFloatConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
    101     LOG(FATAL) << DebugName() << " is not defined for float values";
    102     UNREACHABLE();
    103   }
    104   HConstant* Evaluate(HDoubleConstant* x ATTRIBUTE_UNUSED,
    105                       HDoubleConstant* y ATTRIBUTE_UNUSED) const OVERRIDE {
    106     LOG(FATAL) << DebugName() << " is not defined for double values";
    107     UNREACHABLE();
    108   }
    109 
    110   InstructionKind GetOpKind() const { return op_kind_; }
    111 
    112   DECLARE_INSTRUCTION(BitwiseNegatedRight);
    113 
    114  private:
    115   // Specifies the bitwise operation, which will be then negated.
    116   const InstructionKind op_kind_;
    117 
    118   DISALLOW_COPY_AND_ASSIGN(HBitwiseNegatedRight);
    119 };
    120 
    121 
    122 // This instruction computes an intermediate address pointing in the 'middle' of an object. The
    123 // result pointer cannot be handled by GC, so extra care is taken to make sure that this value is
    124 // never used across anything that can trigger GC.
    125 // The result of this instruction is not a pointer in the sense of `Primitive::kPrimNot`. So we
    126 // represent it by the type `Primitive::kPrimInt`.
    127 class HIntermediateAddress FINAL : public HExpression<2> {
    128  public:
    129   HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc)
    130       : HExpression(Primitive::kPrimInt, SideEffects::DependsOnGC(), dex_pc) {
    131         DCHECK_EQ(Primitive::ComponentSize(Primitive::kPrimInt),
    132                   Primitive::ComponentSize(Primitive::kPrimNot))
    133             << "kPrimInt and kPrimNot have different sizes.";
    134     SetRawInputAt(0, base_address);
    135     SetRawInputAt(1, offset);
    136   }
    137 
    138   bool CanBeMoved() const OVERRIDE { return true; }
    139   bool InstructionDataEquals(const HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
    140     return true;
    141   }
    142   bool IsActualObject() const OVERRIDE { return false; }
    143 
    144   HInstruction* GetBaseAddress() const { return InputAt(0); }
    145   HInstruction* GetOffset() const { return InputAt(1); }
    146 
    147   DECLARE_INSTRUCTION(IntermediateAddress);
    148 
    149  private:
    150   DISALLOW_COPY_AND_ASSIGN(HIntermediateAddress);
    151 };
    152 
    153 class HDataProcWithShifterOp FINAL : public HExpression<2> {
    154  public:
    155   enum OpKind {
    156     kLSL,   // Logical shift left.
    157     kLSR,   // Logical shift right.
    158     kASR,   // Arithmetic shift right.
    159     kUXTB,  // Unsigned extend byte.
    160     kUXTH,  // Unsigned extend half-word.
    161     kUXTW,  // Unsigned extend word.
    162     kSXTB,  // Signed extend byte.
    163     kSXTH,  // Signed extend half-word.
    164     kSXTW,  // Signed extend word.
    165 
    166     // Aliases.
    167     kFirstShiftOp = kLSL,
    168     kLastShiftOp = kASR,
    169     kFirstExtensionOp = kUXTB,
    170     kLastExtensionOp = kSXTW
    171   };
    172   HDataProcWithShifterOp(HInstruction* instr,
    173                          HInstruction* left,
    174                          HInstruction* right,
    175                          OpKind op,
    176                          // The shift argument is unused if the operation
    177                          // is an extension.
    178                          int shift = 0,
    179                          uint32_t dex_pc = kNoDexPc)
    180       : HExpression(instr->GetType(), SideEffects::None(), dex_pc),
    181         instr_kind_(instr->GetKind()), op_kind_(op),
    182         shift_amount_(shift & (instr->GetType() == Primitive::kPrimInt
    183             ? kMaxIntShiftDistance
    184             : kMaxLongShiftDistance)) {
    185     DCHECK(!instr->HasSideEffects());
    186     SetRawInputAt(0, left);
    187     SetRawInputAt(1, right);
    188   }
    189 
    190   bool CanBeMoved() const OVERRIDE { return true; }
    191   bool InstructionDataEquals(const HInstruction* other_instr) const OVERRIDE {
    192     const HDataProcWithShifterOp* other = other_instr->AsDataProcWithShifterOp();
    193     return instr_kind_ == other->instr_kind_ &&
    194         op_kind_ == other->op_kind_ &&
    195         shift_amount_ == other->shift_amount_;
    196   }
    197 
    198   static bool IsShiftOp(OpKind op_kind) {
    199     return kFirstShiftOp <= op_kind && op_kind <= kLastShiftOp;
    200   }
    201 
    202   static bool IsExtensionOp(OpKind op_kind) {
    203     return kFirstExtensionOp <= op_kind && op_kind <= kLastExtensionOp;
    204   }
    205 
    206   // Find the operation kind and shift amount from a bitfield move instruction.
    207   static void GetOpInfoFromInstruction(HInstruction* bitfield_op,
    208                                        /*out*/OpKind* op_kind,
    209                                        /*out*/int* shift_amount);
    210 
    211   InstructionKind GetInstrKind() const { return instr_kind_; }
    212   OpKind GetOpKind() const { return op_kind_; }
    213   int GetShiftAmount() const { return shift_amount_; }
    214 
    215   DECLARE_INSTRUCTION(DataProcWithShifterOp);
    216 
    217  private:
    218   InstructionKind instr_kind_;
    219   OpKind op_kind_;
    220   int shift_amount_;
    221 
    222   friend std::ostream& operator<<(std::ostream& os, OpKind op);
    223 
    224   DISALLOW_COPY_AND_ASSIGN(HDataProcWithShifterOp);
    225 };
    226 
    227 std::ostream& operator<<(std::ostream& os, const HDataProcWithShifterOp::OpKind op);
    228 
    229 }  // namespace art
    230 
    231 #endif  // ART_COMPILER_OPTIMIZING_NODES_SHARED_H_
    232