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

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') | no next file » | 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 intptr_t tmp = (left_int > 0) ? left_int : ~left_int;
2001 intptr_t max_right = kSmiBits;
2002 while ((tmp >>= 1) != 0) {
zra 2013/05/28 19:43:32 Could you use Utils::HighestBit here?
regis 2013/05/28 21:10:15 Done here and for ia32/x64. Note that Utils::High
2003 max_right--;
2004 }
2005 const bool right_needs_check =
2006 (right_range == NULL) ||
2007 !right_range->IsWithin(0, max_right - 1);
2008 if (right_needs_check) {
2009 __ cmp(right,
2010 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
2011 __ b(deopt, CS);
2012 }
2013 __ SmiUntag(right);
2014 __ Lsl(result, left, right);
2015 }
2016 return;
2017 }
2018
2019 const bool right_needs_check =
2020 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2021 if (is_truncating) {
2022 if (right_needs_check) {
2023 const bool right_may_be_negative =
2024 (right_range == NULL) ||
2025 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
2026 if (right_may_be_negative) {
2027 ASSERT(shift_left->CanDeoptimize());
2028 __ cmp(right, ShifterOperand(0));
2029 __ b(deopt, MI);
2030 }
2031 Label done, is_not_zero;
2032 __ cmp(right,
2033 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2034 __ mov(result, ShifterOperand(0), CS);
2035 __ SmiUntag(right, CC);
2036 __ Lsl(result, left, right, CC);
2037 } else {
2038 __ SmiUntag(right);
2039 __ Lsl(result, left, right);
2040 }
2041 } else {
2042 if (right_needs_check) {
2043 ASSERT(shift_left->CanDeoptimize());
2044 __ cmp(right,
2045 ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
2046 __ b(deopt, CS);
2047 }
2048 // Left is not a constant.
2049 // Check if count too large for handling it inlined.
2050 __ SmiUntag(right);
2051 // Overflow test (preserve left and right);
2052 __ Lsl(IP, left, right);
2053 __ cmp(left, ShifterOperand(IP, ASR, right));
2054 __ b(deopt, NE); // Overflow.
2055 // Shift for result now we know there is no overflow.
2056 __ Lsl(result, left, right);
2057 }
2058 }
2059
2060
1948 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2061 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
1949 const intptr_t kNumInputs = 2; 2062 const intptr_t kNumInputs = 2;
1950 if (op_kind() == Token::kTRUNCDIV) { 2063 if (op_kind() == Token::kTRUNCDIV) {
1951 UNIMPLEMENTED(); 2064 UNIMPLEMENTED();
1952 return NULL; 2065 return NULL;
1953 } else { 2066 } else {
1954 const intptr_t kNumTemps = 0; 2067 const intptr_t kNumTemps = 0;
1955 LocationSummary* summary = 2068 LocationSummary* summary =
1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2069 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1957 summary->set_in(0, Location::RequiresRegister()); 2070 summary->set_in(0, Location::RequiresRegister());
1958 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 2071 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1959 // We make use of 3-operand instructions by not requiring result register 2072 // We make use of 3-operand instructions by not requiring result register
1960 // to be identical to first input register as on Intel. 2073 // to be identical to first input register as on Intel.
1961 summary->set_out(Location::RequiresRegister()); 2074 summary->set_out(Location::RequiresRegister());
1962 return summary; 2075 return summary;
1963 } 2076 }
1964 } 2077 }
1965 2078
1966 2079
1967 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2080 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1968 if (op_kind() == Token::kSHL) { 2081 if (op_kind() == Token::kSHL) {
1969 UNIMPLEMENTED(); 2082 EmitSmiShiftLeft(compiler, this);
1970 return; 2083 return;
1971 } 2084 }
1972 2085
1973 ASSERT(!is_truncating()); 2086 ASSERT(!is_truncating());
1974 Register left = locs()->in(0).reg(); 2087 Register left = locs()->in(0).reg();
1975 Register result = locs()->out().reg(); 2088 Register result = locs()->out().reg();
1976 Label* deopt = NULL; 2089 Label* deopt = NULL;
1977 if (CanDeoptimize()) { 2090 if (CanDeoptimize()) {
1978 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); 2091 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
1979 } 2092 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 ShifterOperand shifter_op; 2166 ShifterOperand shifter_op;
2054 if (ShifterOperand::CanHold(imm, &shifter_op)) { 2167 if (ShifterOperand::CanHold(imm, &shifter_op)) {
2055 __ eor(result, left, shifter_op); 2168 __ eor(result, left, shifter_op);
2056 } else { 2169 } else {
2057 __ LoadImmediate(IP, imm); 2170 __ LoadImmediate(IP, imm);
2058 __ eor(result, left, ShifterOperand(IP)); 2171 __ eor(result, left, ShifterOperand(IP));
2059 } 2172 }
2060 break; 2173 break;
2061 } 2174 }
2062 case Token::kSHR: { 2175 case Token::kSHR: {
2063 UNIMPLEMENTED(); 2176 // sarl operation masks the count to 5 bits.
2177 const intptr_t kCountLimit = 0x1F;
2178 intptr_t value = Smi::Cast(constant).Value();
2179
2180 if (value == 0) {
2181 // TODO(vegorov): should be handled outside.
2182 break;
2183 } else if (value < 0) {
2184 // TODO(vegorov): should be handled outside.
2185 __ b(deopt);
2186 break;
2187 }
2188
2189 value = value + kSmiTagSize;
2190 if (value >= kCountLimit) value = kCountLimit;
2191
2192 __ Asr(result, left, value);
2193 __ SmiTag(result);
2064 break; 2194 break;
2065 } 2195 }
2066 2196
2067 default: 2197 default:
2068 UNREACHABLE(); 2198 UNREACHABLE();
2069 break; 2199 break;
2070 } 2200 }
2071 return; 2201 return;
2072 } 2202 }
2073 2203
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after
3023 compiler->GenerateCall(token_pos(), 3153 compiler->GenerateCall(token_pos(),
3024 &label, 3154 &label,
3025 PcDescriptors::kOther, 3155 PcDescriptors::kOther,
3026 locs()); 3156 locs());
3027 __ Drop(2); // Discard type arguments and receiver. 3157 __ Drop(2); // Discard type arguments and receiver.
3028 } 3158 }
3029 3159
3030 } // namespace dart 3160 } // namespace dart
3031 3161
3032 #endif // defined TARGET_ARCH_ARM 3162 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698