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

Side by Side Diff: test/unittests/compiler/arm/instruction-selector-arm-unittest.cc

Issue 2152253002: [ARM] Generate flag setting instructions for arm. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 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
« no previous file with comments | « src/compiler/arm/instruction-selector-arm.cc ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits> 5 #include <limits>
6 6
7 #include "test/unittests/compiler/instruction-selector-unittest.h" 7 #include "test/unittests/compiler/instruction-selector-unittest.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 1986 matching lines...) Expand 10 before | Expand all | Expand 10 after
1997 Stream s = m.Build(); 1997 Stream s = m.Build();
1998 ASSERT_EQ(1U, s.size()); 1998 ASSERT_EQ(1U, s.size());
1999 EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode()); 1999 EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode());
2000 ASSERT_EQ(1U, s[0]->InputCount()); 2000 ASSERT_EQ(1U, s[0]->InputCount());
2001 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2001 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
2002 ASSERT_EQ(1U, s[0]->OutputCount()); 2002 ASSERT_EQ(1U, s[0]->OutputCount());
2003 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2003 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
2004 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 2004 EXPECT_EQ(kFlags_none, s[0]->flags_mode());
2005 } 2005 }
2006 2006
2007 // -----------------------------------------------------------------------------
2008 // Flag-setting instructions.
2009
2010 const Comparison kBinopCmpZeroRightInstructions[] = {
2011 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
2012 kEqual},
2013 {&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kNotEqual, kEqual,
2014 kNotEqual},
2015 {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kNegative,
2016 kPositiveOrZero, kNegative},
2017 {&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual",
2018 kPositiveOrZero, kNegative, kPositiveOrZero},
2019 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
2020 kEqual, kNotEqual, kEqual},
2021 {&RawMachineAssembler::Uint32GreaterThan, "Uint32GreaterThan", kNotEqual,
2022 kEqual, kNotEqual}};
2023
2024 const Comparison kBinopCmpZeroLeftInstructions[] = {
2025 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual,
2026 kEqual},
2027 {&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kNotEqual, kEqual,
2028 kNotEqual},
2029 {&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kNegative,
2030 kPositiveOrZero, kNegative},
2031 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
2032 kPositiveOrZero, kNegative, kPositiveOrZero},
2033 {&RawMachineAssembler::Uint32GreaterThanOrEqual, "Uint32GreaterThanOrEqual",
2034 kEqual, kNotEqual, kEqual},
2035 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kNotEqual, kEqual,
2036 kNotEqual}};
2037
2038 struct FlagSettingInst {
2039 Constructor constructor;
2040 const char* constructor_name;
2041 ArchOpcode arch_opcode;
2042 ArchOpcode no_output_opcode;
2043 };
2044
2045 std::ostream& operator<<(std::ostream& os, const FlagSettingInst& inst) {
2046 return os << inst.constructor_name;
2047 }
2048
2049 const FlagSettingInst kFlagSettingInstructions[] = {
2050 {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmCmn},
2051 {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmTst},
2052 {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr},
2053 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmTeq}};
2054
2055 typedef InstructionSelectorTestWithParam<FlagSettingInst>
2056 InstructionSelectorFlagSettingTest;
2057
2058 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroRight) {
2059 const FlagSettingInst inst = GetParam();
2060 // Binop with single user : a cmp instruction.
2061 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
2062 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2063 MachineType::Int32());
2064 RawMachineLabel a, b;
2065 Node* binop = (m.*inst.constructor)(m.Parameter(0), m.Parameter(1));
2066 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2067 m.Branch(comp, &a, &b);
2068 m.Bind(&a);
2069 m.Return(m.Int32Constant(1));
2070 m.Bind(&b);
2071 m.Return(m.Int32Constant(0));
2072 Stream s = m.Build();
2073 ASSERT_EQ(1U, s.size());
2074 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
2075 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
2076 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
2077 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
2078 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
2079 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2080 }
2081 }
2082
2083 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroLeft) {
2084 const FlagSettingInst inst = GetParam();
2085 // Test a cmp with zero on the left-hand side.
2086 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroLeftInstructions) {
2087 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2088 MachineType::Int32());
2089 RawMachineLabel a, b;
2090 Node* binop = (m.*inst.constructor)(m.Parameter(0), m.Parameter(1));
2091 Node* comp = (m.*cmp.constructor)(m.Int32Constant(0), binop);
2092 m.Branch(comp, &a, &b);
2093 m.Bind(&a);
2094 m.Return(m.Int32Constant(1));
2095 m.Bind(&b);
2096 m.Return(m.Int32Constant(0));
2097 Stream s = m.Build();
2098 ASSERT_EQ(1U, s.size());
2099 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
2100 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
2101 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
2102 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
2103 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
2104 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2105 }
2106 }
2107
2108 TEST_P(InstructionSelectorFlagSettingTest, CmpZeroOnlyUserInBasicBlock) {
2109 const FlagSettingInst inst = GetParam();
2110 // Binop with additional users, but in a different basic block.
2111 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
2112 // We don't optimise this case at the moment.
2113 if (cmp.flags_condition == kEqual || cmp.flags_condition == kNotEqual) {
2114 continue;
2115 }
2116 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2117 MachineType::Int32());
2118 RawMachineLabel a, b;
2119 Node* binop = (m.*inst.constructor)(m.Parameter(0), m.Parameter(1));
2120 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2121 m.Branch(comp, &a, &b);
2122 m.Bind(&a);
2123 m.Return(binop);
2124 m.Bind(&b);
2125 m.Return(m.Int32Constant(0));
2126 Stream s = m.Build();
2127 ASSERT_EQ(1U, s.size());
2128 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
2129 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
2130 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
2131 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
2132 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
2133 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2134 }
2135 }
2136
2137 TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
2138 const FlagSettingInst inst = GetParam();
2139 // Like the test above, but with a shifted input to the binary operator.
2140 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
2141 // We don't optimise this case at the moment.
2142 if (cmp.flags_condition == kEqual || cmp.flags_condition == kNotEqual) {
2143 continue;
2144 }
2145 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2146 MachineType::Int32());
2147 RawMachineLabel a, b;
2148 Node* imm = m.Int32Constant(5);
2149 Node* shift = m.Word32Shl(m.Parameter(1), imm);
2150 Node* binop = (m.*inst.constructor)(m.Parameter(0), shift);
2151 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2152 m.Branch(comp, &a, &b);
2153 m.Bind(&a);
2154 m.Return(binop);
2155 m.Bind(&b);
2156 m.Return(m.Int32Constant(0));
2157 Stream s = m.Build();
2158 ASSERT_EQ(1U, s.size());
2159 ASSERT_EQ(5U, s[0]->InputCount()); // The labels are also inputs.
2160 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
2161 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
2162 EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
2163 EXPECT_EQ(5, s.ToInt32(s[0]->InputAt(2)));
2164 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
2165 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
2166 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2167 }
2168 }
2169
2170 TEST_P(InstructionSelectorFlagSettingTest, UsersInSameBasicBlock) {
2171 const FlagSettingInst inst = GetParam();
2172 // Binop with additional users, in the same basic block. We need to make sure
2173 // we don't try to optimise this case.
2174 TRACED_FOREACH(Comparison, cmp, kComparisons) {
2175 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2176 MachineType::Int32());
2177 RawMachineLabel a, b;
2178 Node* binop = (m.*inst.constructor)(m.Parameter(0), m.Parameter(1));
2179 Node* mul = m.Int32Mul(m.Parameter(0), binop);
2180 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2181 m.Branch(comp, &a, &b);
2182 m.Bind(&a);
2183 m.Return(mul);
2184 m.Bind(&b);
2185 m.Return(m.Int32Constant(0));
2186 Stream s = m.Build();
2187 ASSERT_EQ(3U, s.size());
2188 EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
2189 EXPECT_NE(kFlags_branch, s[0]->flags_mode());
2190 EXPECT_EQ(kArmMul, s[1]->arch_opcode());
2191 EXPECT_EQ(cmp.flags_condition == kEqual ? kArmTst : kArmCmp,
2192 s[2]->arch_opcode());
2193 EXPECT_EQ(kFlags_branch, s[2]->flags_mode());
2194 EXPECT_EQ(cmp.flags_condition, s[2]->flags_condition());
2195 }
2196 }
2197
2198 TEST_P(InstructionSelectorFlagSettingTest, CommuteImmediate) {
2199 const FlagSettingInst inst = GetParam();
2200 // Immediate on left hand side of the binary operator.
2201 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
2202 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
2203 RawMachineLabel a, b;
2204 Node* imm = m.Int32Constant(3);
2205 Node* binop = (m.*inst.constructor)(imm, m.Parameter(0));
2206 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2207 m.Branch(comp, &a, &b);
2208 m.Bind(&a);
2209 m.Return(m.Int32Constant(1));
2210 m.Bind(&b);
2211 m.Return(m.Int32Constant(0));
2212 Stream s = m.Build();
2213 ASSERT_EQ(1U, s.size());
2214 ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
2215 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
2216 EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
2217 EXPECT_EQ(3, s.ToInt32(s[0]->InputAt(1)));
2218 EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
2219 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2220 }
2221 }
2222
2223 TEST_P(InstructionSelectorFlagSettingTest, CommuteShift) {
2224 const FlagSettingInst inst = GetParam();
2225 // Left-hand side operand shifted by immediate.
2226 TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
2227 TRACED_FOREACH(Shift, shift, kShifts) {
2228 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2229 MachineType::Int32());
2230 Node* imm = m.Int32Constant(5);
2231 Node* shifted_operand = (m.*shift.constructor)(m.Parameter(0), imm);
2232 Node* binop = (m.*inst.constructor)(shifted_operand, m.Parameter(1));
2233 Node* comp = (m.*cmp.constructor)(binop, m.Int32Constant(0));
2234 m.Return(comp);
2235 Stream s = m.Build();
2236 ASSERT_EQ(1U, s.size());
2237 EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
2238 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode());
2239 EXPECT_EQ(3U, s[0]->InputCount());
2240 EXPECT_EQ(5, s.ToInt64(s[0]->InputAt(2)));
2241 EXPECT_EQ(inst.arch_opcode == kArmOrr ? 2U : 1U, s[0]->OutputCount());
2242 EXPECT_EQ(kFlags_set, s[0]->flags_mode());
2243 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
2244 }
2245 }
2246 }
2247
2248 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
2249 InstructionSelectorFlagSettingTest,
2250 ::testing::ValuesIn(kFlagSettingInstructions));
2007 2251
2008 // ----------------------------------------------------------------------------- 2252 // -----------------------------------------------------------------------------
2009 // Miscellaneous. 2253 // Miscellaneous.
2010 2254
2011 2255
2012 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { 2256 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) {
2013 { 2257 {
2014 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2258 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
2015 MachineType::Int32(), MachineType::Int32()); 2259 MachineType::Int32(), MachineType::Int32());
2016 Node* const p0 = m.Parameter(0); 2260 Node* const p0 = m.Parameter(0);
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode()); 3329 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode());
3086 ASSERT_EQ(1U, s[0]->InputCount()); 3330 ASSERT_EQ(1U, s[0]->InputCount());
3087 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3331 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
3088 ASSERT_EQ(1U, s[0]->OutputCount()); 3332 ASSERT_EQ(1U, s[0]->OutputCount());
3089 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3333 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
3090 } 3334 }
3091 3335
3092 } // namespace compiler 3336 } // namespace compiler
3093 } // namespace internal 3337 } // namespace internal
3094 } // namespace v8 3338 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm/instruction-selector-arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698