Home | History | Annotate | Download | only in optimizing
      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 #include "base/arena_allocator.h"
     18 #include "nodes.h"
     19 #include "optimizing_unit_test.h"
     20 
     21 namespace art {
     22 
     23 /**
     24  * Fixture class for testing vector nodes.
     25  */
     26 class NodesVectorTest : public CommonCompilerTest {
     27  public:
     28   NodesVectorTest()
     29       : pool_(),
     30         allocator_(&pool_),
     31         graph_(CreateGraph(&allocator_)) {
     32     BuildGraph();
     33   }
     34 
     35   ~NodesVectorTest() { }
     36 
     37   void BuildGraph() {
     38     graph_->SetNumberOfVRegs(1);
     39     entry_block_ = new (&allocator_) HBasicBlock(graph_);
     40     exit_block_ = new (&allocator_) HBasicBlock(graph_);
     41     graph_->AddBlock(entry_block_);
     42     graph_->AddBlock(exit_block_);
     43     graph_->SetEntryBlock(entry_block_);
     44     graph_->SetExitBlock(exit_block_);
     45     parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
     46                                                    dex::TypeIndex(0),
     47                                                    0,
     48                                                    Primitive::kPrimInt);
     49     entry_block_->AddInstruction(parameter_);
     50   }
     51 
     52   // General building fields.
     53   ArenaPool pool_;
     54   ArenaAllocator allocator_;
     55   HGraph* graph_;
     56 
     57   HBasicBlock* entry_block_;
     58   HBasicBlock* exit_block_;
     59 
     60   HInstruction* parameter_;
     61 };
     62 
     63 //
     64 // The actual vector nodes tests.
     65 //
     66 
     67 TEST(NodesVector, Alignment) {
     68   EXPECT_TRUE(Alignment(1, 0).IsAlignedAt(1));
     69   EXPECT_FALSE(Alignment(1, 0).IsAlignedAt(2));
     70 
     71   EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(1));
     72   EXPECT_TRUE(Alignment(2, 1).IsAlignedAt(1));
     73   EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(2));
     74   EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(2));
     75   EXPECT_FALSE(Alignment(2, 0).IsAlignedAt(4));
     76   EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(4));
     77 
     78   EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(1));
     79   EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(1));
     80   EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(2));
     81   EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(2));
     82   EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(4));
     83   EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(4));
     84   EXPECT_FALSE(Alignment(4, 0).IsAlignedAt(8));
     85   EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(8));
     86 
     87   EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(1));
     88   EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(2));
     89   EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(4));
     90   EXPECT_TRUE(Alignment(16, 8).IsAlignedAt(8));
     91   EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(16));
     92   EXPECT_FALSE(Alignment(16, 1).IsAlignedAt(16));
     93   EXPECT_FALSE(Alignment(16, 7).IsAlignedAt(16));
     94   EXPECT_FALSE(Alignment(16, 0).IsAlignedAt(32));
     95 }
     96 
     97 TEST(NodesVector, AlignmentEQ) {
     98   EXPECT_TRUE(Alignment(2, 0) == Alignment(2, 0));
     99   EXPECT_TRUE(Alignment(2, 1) == Alignment(2, 1));
    100   EXPECT_TRUE(Alignment(4, 0) == Alignment(4, 0));
    101   EXPECT_TRUE(Alignment(4, 2) == Alignment(4, 2));
    102 
    103   EXPECT_FALSE(Alignment(4, 0) == Alignment(2, 0));
    104   EXPECT_FALSE(Alignment(4, 0) == Alignment(4, 1));
    105   EXPECT_FALSE(Alignment(4, 0) == Alignment(8, 0));
    106 }
    107 
    108 TEST(NodesVector, AlignmentString) {
    109   EXPECT_STREQ("ALIGN(1,0)", Alignment(1, 0).ToString().c_str());
    110 
    111   EXPECT_STREQ("ALIGN(2,0)", Alignment(2, 0).ToString().c_str());
    112   EXPECT_STREQ("ALIGN(2,1)", Alignment(2, 1).ToString().c_str());
    113 
    114   EXPECT_STREQ("ALIGN(16,0)", Alignment(16, 0).ToString().c_str());
    115   EXPECT_STREQ("ALIGN(16,1)", Alignment(16, 1).ToString().c_str());
    116   EXPECT_STREQ("ALIGN(16,8)", Alignment(16, 8).ToString().c_str());
    117   EXPECT_STREQ("ALIGN(16,9)", Alignment(16, 9).ToString().c_str());
    118 }
    119 
    120 TEST_F(NodesVectorTest, VectorOperationProperties) {
    121   HVecOperation* v0 = new (&allocator_)
    122       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    123   HVecOperation* v1 = new (&allocator_)
    124       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    125   HVecOperation* v2 = new (&allocator_)
    126       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 2);
    127   HVecOperation* v3 = new (&allocator_)
    128       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimShort, 4);
    129   HVecOperation* v4 = new (&allocator_)
    130       HVecStore(&allocator_, parameter_, parameter_, v0, Primitive::kPrimInt, 4);
    131 
    132   EXPECT_TRUE(v0->Equals(v0));
    133   EXPECT_TRUE(v1->Equals(v1));
    134   EXPECT_TRUE(v2->Equals(v2));
    135   EXPECT_TRUE(v3->Equals(v3));
    136   EXPECT_TRUE(v4->Equals(v4));
    137 
    138   EXPECT_TRUE(v0->Equals(v1));
    139   EXPECT_FALSE(v0->Equals(v2));  // different vector lengths
    140   EXPECT_FALSE(v0->Equals(v3));  // different packed types
    141   EXPECT_FALSE(v0->Equals(v4));  // different kinds
    142 
    143   EXPECT_TRUE(v1->Equals(v0));  // switch operands
    144   EXPECT_FALSE(v4->Equals(v0));
    145 
    146   EXPECT_EQ(4u, v0->GetVectorLength());
    147   EXPECT_EQ(4u, v1->GetVectorLength());
    148   EXPECT_EQ(2u, v2->GetVectorLength());
    149   EXPECT_EQ(4u, v3->GetVectorLength());
    150   EXPECT_EQ(4u, v4->GetVectorLength());
    151 
    152   EXPECT_EQ(Primitive::kPrimDouble, v0->GetType());
    153   EXPECT_EQ(Primitive::kPrimDouble, v1->GetType());
    154   EXPECT_EQ(Primitive::kPrimDouble, v2->GetType());
    155   EXPECT_EQ(Primitive::kPrimDouble, v3->GetType());
    156   EXPECT_EQ(Primitive::kPrimDouble, v4->GetType());
    157 
    158   EXPECT_EQ(Primitive::kPrimInt, v0->GetPackedType());
    159   EXPECT_EQ(Primitive::kPrimInt, v1->GetPackedType());
    160   EXPECT_EQ(Primitive::kPrimInt, v2->GetPackedType());
    161   EXPECT_EQ(Primitive::kPrimShort, v3->GetPackedType());
    162   EXPECT_EQ(Primitive::kPrimInt, v4->GetPackedType());
    163 
    164   EXPECT_EQ(16u, v0->GetVectorNumberOfBytes());
    165   EXPECT_EQ(16u, v1->GetVectorNumberOfBytes());
    166   EXPECT_EQ(8u, v2->GetVectorNumberOfBytes());
    167   EXPECT_EQ(8u, v3->GetVectorNumberOfBytes());
    168   EXPECT_EQ(16u, v4->GetVectorNumberOfBytes());
    169 
    170   EXPECT_FALSE(v0->CanBeMoved());
    171   EXPECT_FALSE(v1->CanBeMoved());
    172   EXPECT_FALSE(v2->CanBeMoved());
    173   EXPECT_FALSE(v3->CanBeMoved());
    174   EXPECT_FALSE(v4->CanBeMoved());
    175 }
    176 
    177 TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) {
    178   HVecLoad* v0 = new (&allocator_)
    179       HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false);
    180   HVecLoad* v1 = new (&allocator_)
    181       HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false);
    182   HVecLoad* v2 = new (&allocator_)
    183       HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ true);
    184 
    185   EXPECT_TRUE(v0->CanBeMoved());
    186   EXPECT_TRUE(v1->CanBeMoved());
    187   EXPECT_TRUE(v2->CanBeMoved());
    188 
    189   EXPECT_FALSE(v0->IsStringCharAt());
    190   EXPECT_FALSE(v1->IsStringCharAt());
    191   EXPECT_TRUE(v2->IsStringCharAt());
    192 
    193   EXPECT_TRUE(v0->Equals(v0));
    194   EXPECT_TRUE(v1->Equals(v1));
    195   EXPECT_TRUE(v2->Equals(v2));
    196 
    197   EXPECT_TRUE(v0->Equals(v1));
    198   EXPECT_FALSE(v0->Equals(v2));
    199 
    200   EXPECT_TRUE(v0->GetAlignment() == Alignment(4, 0));
    201   EXPECT_TRUE(v1->GetAlignment() == Alignment(4, 0));
    202   EXPECT_TRUE(v2->GetAlignment() == Alignment(4, 0));
    203 
    204   v1->SetAlignment(Alignment(8, 0));
    205 
    206   EXPECT_TRUE(v1->GetAlignment() == Alignment(8, 0));
    207 
    208   EXPECT_FALSE(v0->Equals(v1));  // no longer equal
    209 }
    210 
    211 TEST_F(NodesVectorTest, VectorSignMattersOnMin) {
    212   HVecOperation* v0 = new (&allocator_)
    213       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    214 
    215   HVecMin* v1 = new (&allocator_)
    216       HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true);
    217   HVecMin* v2 = new (&allocator_)
    218       HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false);
    219   HVecMin* v3 = new (&allocator_)
    220       HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true);
    221 
    222   EXPECT_FALSE(v0->CanBeMoved());
    223   EXPECT_TRUE(v1->CanBeMoved());
    224   EXPECT_TRUE(v2->CanBeMoved());
    225   EXPECT_TRUE(v3->CanBeMoved());
    226 
    227   EXPECT_TRUE(v1->IsUnsigned());
    228   EXPECT_FALSE(v2->IsUnsigned());
    229   EXPECT_TRUE(v3->IsUnsigned());
    230 
    231   EXPECT_TRUE(v1->Equals(v1));
    232   EXPECT_TRUE(v2->Equals(v2));
    233   EXPECT_TRUE(v3->Equals(v3));
    234 
    235   EXPECT_FALSE(v1->Equals(v2));  // different signs
    236   EXPECT_FALSE(v1->Equals(v3));  // different vector lengths
    237 }
    238 
    239 TEST_F(NodesVectorTest, VectorSignMattersOnMax) {
    240   HVecOperation* v0 = new (&allocator_)
    241       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    242 
    243   HVecMax* v1 = new (&allocator_)
    244       HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true);
    245   HVecMax* v2 = new (&allocator_)
    246       HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false);
    247   HVecMax* v3 = new (&allocator_)
    248       HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true);
    249 
    250   EXPECT_FALSE(v0->CanBeMoved());
    251   EXPECT_TRUE(v1->CanBeMoved());
    252   EXPECT_TRUE(v2->CanBeMoved());
    253   EXPECT_TRUE(v3->CanBeMoved());
    254 
    255   EXPECT_TRUE(v1->IsUnsigned());
    256   EXPECT_FALSE(v2->IsUnsigned());
    257   EXPECT_TRUE(v3->IsUnsigned());
    258 
    259   EXPECT_TRUE(v1->Equals(v1));
    260   EXPECT_TRUE(v2->Equals(v2));
    261   EXPECT_TRUE(v3->Equals(v3));
    262 
    263   EXPECT_FALSE(v1->Equals(v2));  // different signs
    264   EXPECT_FALSE(v1->Equals(v3));  // different vector lengths
    265 }
    266 
    267 TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) {
    268   HVecOperation* v0 = new (&allocator_)
    269       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    270 
    271   HVecHalvingAdd* v1 = new (&allocator_) HVecHalvingAdd(
    272       &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ true);
    273   HVecHalvingAdd* v2 = new (&allocator_) HVecHalvingAdd(
    274       &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ false);
    275   HVecHalvingAdd* v3 = new (&allocator_) HVecHalvingAdd(
    276       &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ true);
    277   HVecHalvingAdd* v4 = new (&allocator_) HVecHalvingAdd(
    278       &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ false);
    279   HVecHalvingAdd* v5 = new (&allocator_) HVecHalvingAdd(
    280       &allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true, /*is_rounded*/ true);
    281 
    282   EXPECT_FALSE(v0->CanBeMoved());
    283   EXPECT_TRUE(v1->CanBeMoved());
    284   EXPECT_TRUE(v2->CanBeMoved());
    285   EXPECT_TRUE(v3->CanBeMoved());
    286   EXPECT_TRUE(v4->CanBeMoved());
    287   EXPECT_TRUE(v5->CanBeMoved());
    288 
    289   EXPECT_TRUE(v1->Equals(v1));
    290   EXPECT_TRUE(v2->Equals(v2));
    291   EXPECT_TRUE(v3->Equals(v3));
    292   EXPECT_TRUE(v4->Equals(v4));
    293   EXPECT_TRUE(v5->Equals(v5));
    294 
    295   EXPECT_TRUE(v1->IsUnsigned() && v1->IsRounded());
    296   EXPECT_TRUE(v2->IsUnsigned() && !v2->IsRounded());
    297   EXPECT_TRUE(!v3->IsUnsigned() && v3->IsRounded());
    298   EXPECT_TRUE(!v4->IsUnsigned() && !v4->IsRounded());
    299   EXPECT_TRUE(v5->IsUnsigned() && v5->IsRounded());
    300 
    301   EXPECT_FALSE(v1->Equals(v2));  // different attributes
    302   EXPECT_FALSE(v1->Equals(v3));  // different attributes
    303   EXPECT_FALSE(v1->Equals(v4));  // different attributes
    304   EXPECT_FALSE(v1->Equals(v5));  // different vector lengths
    305 }
    306 
    307 TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) {
    308   HVecOperation* v0 = new (&allocator_)
    309       HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
    310 
    311   HVecMultiplyAccumulate* v1 = new (&allocator_)
    312       HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 4);
    313   HVecMultiplyAccumulate* v2 = new (&allocator_)
    314       HVecMultiplyAccumulate(&allocator_, HInstruction::kSub, v0, v0, v0, Primitive::kPrimInt, 4);
    315   HVecMultiplyAccumulate* v3 = new (&allocator_)
    316       HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 2);
    317 
    318   EXPECT_FALSE(v0->CanBeMoved());
    319   EXPECT_TRUE(v1->CanBeMoved());
    320   EXPECT_TRUE(v2->CanBeMoved());
    321   EXPECT_TRUE(v3->CanBeMoved());
    322 
    323   EXPECT_EQ(HInstruction::kAdd, v1->GetOpKind());
    324   EXPECT_EQ(HInstruction::kSub, v2->GetOpKind());
    325   EXPECT_EQ(HInstruction::kAdd, v3->GetOpKind());
    326 
    327   EXPECT_TRUE(v1->Equals(v1));
    328   EXPECT_TRUE(v2->Equals(v2));
    329   EXPECT_TRUE(v3->Equals(v3));
    330 
    331   EXPECT_FALSE(v1->Equals(v2));  // different operators
    332   EXPECT_FALSE(v1->Equals(v3));  // different vector lengths
    333 }
    334 
    335 }  // namespace art
    336