Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 15827006: Implement shift left on ARM and re-enable previously disabled test. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 1927 matching lines...) Expand 10 before | Expand all | Expand 10 after
1938 compiler->AddSlowPathCode(slow_path); 1938 compiler->AddSlowPathCode(slow_path);
1939 1939
1940 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); 1940 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
1941 __ ldr(IP, Address(IP)); 1941 __ ldr(IP, Address(IP));
1942 __ cmp(SP, ShifterOperand(IP)); 1942 __ cmp(SP, ShifterOperand(IP));
1943 __ b(slow_path->entry_label(), LS); 1943 __ b(slow_path->entry_label(), LS);
1944 __ Bind(slow_path->exit_label()); 1944 __ Bind(slow_path->exit_label());
1945 } 1945 }
1946 1946
1947 1947
1948 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
1949 BinarySmiOpInstr* shift_left) {
1950 const bool is_truncating = shift_left->is_truncating();
1951 const LocationSummary& locs = *shift_left->locs();
1952 Register left = locs.in(0).reg();
1953 Register result = locs.out().reg();
1954 Label* deopt = shift_left->CanDeoptimize() ?
1955 compiler->AddDeoptStub(shift_left->deopt_id(), kDeoptBinarySmiOp) : NULL;
1956 if (locs.in(1).IsConstant()) {
1957 const Object& constant = locs.in(1).constant();
1958 ASSERT(constant.IsSmi());
1959 // Immediate shift operation takes 5 bits for the count.
1960 const intptr_t kCountLimit = 0x1F;
1961 const intptr_t value = Smi::Cast(constant).Value();
1962 if (value == 0) {
1963 // No code needed.
1964 } else if ((value < 0) || (value >= kCountLimit)) {
1965 // This condition may not be known earlier in some cases because
1966 // of constant propagation, inlining, etc.
1967 if ((value >=kCountLimit) && is_truncating) {
1968 __ mov(result, ShifterOperand(0));
1969 } else {
1970 // Result is Mint or exception.
1971 __ b(deopt);
1972 }
1973 } else {
1974 if (!is_truncating) {
1975 // Check for overflow (preserve left).
1976 __ Lsl(IP, left, value);
1977 __ cmp(left, ShifterOperand(IP, ASR, value));
1978 __ b(deopt, NE); // Overflow.
1979 }
1980 // Shift for result now we know there is no overflow.
1981 __ Lsl(result, left, value);
1982 }
1983 return;
1984 }
1985
1986 // Right (locs.in(1)) is not constant.
1987 Register right = locs.in(1).reg();
1988 Range* right_range = shift_left->right()->definition()->range();
1989 if (shift_left->left()->BindsToConstant() && !is_truncating) {
1990 // TODO(srdjan): Implement code below for is_truncating().
1991 // If left is constant, we know the maximal allowed size for right.
1992 const Object& obj = shift_left->left()->BoundConstant();
1993 if (obj.IsSmi()) {
1994 const intptr_t left_int = Smi::Cast(obj).Value();
1995 if (left_int == 0) {
1996 __ cmp(right, ShifterOperand(0));
1997 __ b(deopt, MI);
1998 return;
1999 }
2000 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2001 const bool right_needs_check =
2002 (right_range == NULL) ||
2003 !right_range->IsWithin(0, max_right - 1);
2004 if (right_needs_check) {
2005 __ cmp(right,
2006 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
2007 __ b(deopt, CS);
2008 }
2009 __ SmiUntag(right);
2010 __ Lsl(result, left, right);
2011 }
2012 return;
2013 }
2014
2015 const bool right_needs_check =
2016 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2017 if (is_truncating) {
2018 if (right_needs_check) {
2019 const bool right_may_be_negative =
2020 (right_range == NULL) ||
2021 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
2022 if (right_may_be_negative) {
2023 ASSERT(shift_left->CanDeoptimize());
2024 __ cmp(right, ShifterOperand(0));
2025 __ b(deopt, MI);
2026 }
2027 Label done, is_not_zero;
2028 __ cmp(right,
2029 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2030 __ mov(result, ShifterOperand(0), CS);
2031 __ SmiUntag(right, CC);
2032 __ Lsl(result, left, right, CC);
2033 } else {
2034 __ SmiUntag(right);
2035 __ Lsl(result, left, right);
2036 }
2037 } else {
2038 if (right_needs_check) {
2039 ASSERT(shift_left->CanDeoptimize());
2040 __ cmp(right,
2041 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2042 __ b(deopt, CS);
2043 }
2044 // Left is not a constant.
2045 // Check if count too large for handling it inlined.
2046 __ SmiUntag(right);
2047 // Overflow test (preserve left and right);
2048 __ Lsl(IP, left, right);
2049 __ cmp(left, ShifterOperand(IP, ASR, right));
2050 __ b(deopt, NE); // Overflow.
2051 // Shift for result now we know there is no overflow.
2052 __ Lsl(result, left, right);
2053 }
2054 }
2055
2056
1948 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2057 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
1949 const intptr_t kNumInputs = 2; 2058 const intptr_t kNumInputs = 2;
1950 if (op_kind() == Token::kTRUNCDIV) { 2059 if (op_kind() == Token::kTRUNCDIV) {
1951 UNIMPLEMENTED(); 2060 UNIMPLEMENTED();
1952 return NULL; 2061 return NULL;
1953 } else { 2062 } else {
1954 const intptr_t kNumTemps = 0; 2063 const intptr_t kNumTemps = 0;
1955 LocationSummary* summary = 2064 LocationSummary* summary =
1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2065 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1957 summary->set_in(0, Location::RequiresRegister()); 2066 summary->set_in(0, Location::RequiresRegister());
1958 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2067 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1959 // We make use of 3-operand instructions by not requiring result register 2068 // We make use of 3-operand instructions by not requiring result register
1960 // to be identical to first input register as on Intel. 2069 // to be identical to first input register as on Intel.
1961 summary->set_out(Location::RequiresRegister()); 2070 summary->set_out(Location::RequiresRegister());
1962 return summary; 2071 return summary;
1963 } 2072 }
1964 } 2073 }
1965 2074
1966 2075
1967 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2076 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1968 if (op_kind() == Token::kSHL) { 2077 if (op_kind() == Token::kSHL) {
1969 UNIMPLEMENTED(); 2078 EmitSmiShiftLeft(compiler, this);
1970 return; 2079 return;
1971 } 2080 }
1972 2081
1973 ASSERT(!is_truncating()); 2082 ASSERT(!is_truncating());
1974 Register left = locs()->in(0).reg(); 2083 Register left = locs()->in(0).reg();
1975 Register result = locs()->out().reg(); 2084 Register result = locs()->out().reg();
1976 Label* deopt = NULL; 2085 Label* deopt = NULL;
1977 if (CanDeoptimize()) { 2086 if (CanDeoptimize()) {
1978 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); 2087 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
1979 } 2088 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 ShifterOperand shifter_op; 2162 ShifterOperand shifter_op;
2054 if (ShifterOperand::CanHold(imm, &shifter_op)) { 2163 if (ShifterOperand::CanHold(imm, &shifter_op)) {
2055 __ eor(result, left, shifter_op); 2164 __ eor(result, left, shifter_op);
2056 } else { 2165 } else {
2057 __ LoadImmediate(IP, imm); 2166 __ LoadImmediate(IP, imm);
2058 __ eor(result, left, ShifterOperand(IP)); 2167 __ eor(result, left, ShifterOperand(IP));
2059 } 2168 }
2060 break; 2169 break;
2061 } 2170 }
2062 case Token::kSHR: { 2171 case Token::kSHR: {
2063 UNIMPLEMENTED(); 2172 // sarl operation masks the count to 5 bits.
2173 const intptr_t kCountLimit = 0x1F;
2174 intptr_t value = Smi::Cast(constant).Value();
2175
2176 if (value == 0) {
2177 // TODO(vegorov): should be handled outside.
2178 break;
2179 } else if (value < 0) {
2180 // TODO(vegorov): should be handled outside.
2181 __ b(deopt);
2182 break;
2183 }
2184
2185 value = value + kSmiTagSize;
2186 if (value >= kCountLimit) value = kCountLimit;
2187
2188 __ Asr(result, left, value);
2189 __ SmiTag(result);
2064 break; 2190 break;
2065 } 2191 }
2066 2192
2067 default: 2193 default:
2068 UNREACHABLE(); 2194 UNREACHABLE();
2069 break; 2195 break;
2070 } 2196 }
2071 return; 2197 return;
2072 } 2198 }
2073 2199
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after
3023 compiler->GenerateCall(token_pos(), 3149 compiler->GenerateCall(token_pos(),
3024 &label, 3150 &label,
3025 PcDescriptors::kOther, 3151 PcDescriptors::kOther,
3026 locs()); 3152 locs());
3027 __ Drop(2); // Discard type arguments and receiver. 3153 __ Drop(2); // Discard type arguments and receiver.
3028 } 3154 }
3029 3155
3030 } // namespace dart 3156 } // namespace dart
3031 3157
3032 #endif // defined TARGET_ARCH_ARM 3158 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698