1 /* 2 * Copyright (C) 2017 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 // Note: this include order may seem strange and is against the regular style. However it is the 18 // required order as nodes_shared does not have the right dependency chain and compilation 19 // will fail (as AsType on HInstruction will be defined before the full Instruction). 20 #include "nodes.h" 21 22 #include "nodes_shared.h" 23 24 #include "common_arm64.h" 25 26 namespace art { 27 28 using helpers::CanFitInShifterOperand; 29 30 void HDataProcWithShifterOp::GetOpInfoFromInstruction(HInstruction* instruction, 31 /*out*/OpKind* op_kind, 32 /*out*/int* shift_amount) { 33 DCHECK(CanFitInShifterOperand(instruction)); 34 if (instruction->IsShl()) { 35 *op_kind = kLSL; 36 *shift_amount = instruction->AsShl()->GetRight()->AsIntConstant()->GetValue(); 37 } else if (instruction->IsShr()) { 38 *op_kind = kASR; 39 *shift_amount = instruction->AsShr()->GetRight()->AsIntConstant()->GetValue(); 40 } else if (instruction->IsUShr()) { 41 *op_kind = kLSR; 42 *shift_amount = instruction->AsUShr()->GetRight()->AsIntConstant()->GetValue(); 43 } else { 44 DCHECK(instruction->IsTypeConversion()); 45 DataType::Type result_type = instruction->AsTypeConversion()->GetResultType(); 46 DataType::Type input_type = instruction->AsTypeConversion()->GetInputType(); 47 int result_size = DataType::Size(result_type); 48 int input_size = DataType::Size(input_type); 49 int min_size = std::min(result_size, input_size); 50 if (result_type == DataType::Type::kInt32 && input_type == DataType::Type::kInt64) { 51 // There is actually nothing to do. On ARM the high register from the 52 // pair will be ignored. On ARM64 the register will be used as a W 53 // register, discarding the top bits. This is represented by the 54 // default encoding 'LSL 0'. 55 *op_kind = kLSL; 56 *shift_amount = 0; 57 } else if (result_type == DataType::Type::kUint8 || 58 (input_type == DataType::Type::kUint8 && input_size < result_size)) { 59 *op_kind = kUXTB; 60 } else if (result_type == DataType::Type::kUint16 || 61 (input_type == DataType::Type::kUint16 && input_size < result_size)) { 62 *op_kind = kUXTH; 63 } else { 64 switch (min_size) { 65 case 1: *op_kind = kSXTB; break; 66 case 2: *op_kind = kSXTH; break; 67 case 4: *op_kind = kSXTW; break; 68 default: 69 LOG(FATAL) << "Unexpected min size " << min_size; 70 } 71 } 72 } 73 } 74 75 std::ostream& operator<<(std::ostream& os, const HDataProcWithShifterOp::OpKind op) { 76 switch (op) { 77 case HDataProcWithShifterOp::kLSL: return os << "LSL"; 78 case HDataProcWithShifterOp::kLSR: return os << "LSR"; 79 case HDataProcWithShifterOp::kASR: return os << "ASR"; 80 case HDataProcWithShifterOp::kUXTB: return os << "UXTB"; 81 case HDataProcWithShifterOp::kUXTH: return os << "UXTH"; 82 case HDataProcWithShifterOp::kUXTW: return os << "UXTW"; 83 case HDataProcWithShifterOp::kSXTB: return os << "SXTB"; 84 case HDataProcWithShifterOp::kSXTH: return os << "SXTH"; 85 case HDataProcWithShifterOp::kSXTW: return os << "SXTW"; 86 default: 87 LOG(FATAL) << "Invalid OpKind " << static_cast<int>(op); 88 UNREACHABLE(); 89 } 90 } 91 92 } // namespace art 93