1*318c69deSSander de Smalen #include "AArch64RegisterInfo.h" 2*318c69deSSander de Smalen #include "AArch64InstrInfo.h" 3*318c69deSSander de Smalen #include "AArch64Subtarget.h" 4*318c69deSSander de Smalen #include "AArch64TargetMachine.h" 5*318c69deSSander de Smalen #include "llvm/MC/MCSubtargetInfo.h" 6*318c69deSSander de Smalen #include "llvm/MC/TargetRegistry.h" 7*318c69deSSander de Smalen #include "llvm/Support/TargetSelect.h" 8*318c69deSSander de Smalen #include "llvm/Support/raw_ostream.h" 9*318c69deSSander de Smalen #include "llvm/Target/TargetMachine.h" 10*318c69deSSander de Smalen #include "llvm/Target/TargetOptions.h" 11*318c69deSSander de Smalen 12*318c69deSSander de Smalen #include "gtest/gtest.h" 13*318c69deSSander de Smalen 14*318c69deSSander de Smalen #define GET_COMPUTE_FEATURES 15*318c69deSSander de Smalen #include "AArch64GenInstrInfo.inc" 16*318c69deSSander de Smalen 17*318c69deSSander de Smalen using namespace llvm; 18*318c69deSSander de Smalen 19*318c69deSSander de Smalen namespace { 20*318c69deSSander de Smalen 21*318c69deSSander de Smalen std::unique_ptr<TargetMachine> createTargetMachine(const std::string &CPU) { 22*318c69deSSander de Smalen auto TT(Triple::normalize("aarch64--")); 23*318c69deSSander de Smalen 24*318c69deSSander de Smalen LLVMInitializeAArch64TargetInfo(); 25*318c69deSSander de Smalen LLVMInitializeAArch64Target(); 26*318c69deSSander de Smalen LLVMInitializeAArch64TargetMC(); 27*318c69deSSander de Smalen 28*318c69deSSander de Smalen std::string Error; 29*318c69deSSander de Smalen const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 30*318c69deSSander de Smalen 31*318c69deSSander de Smalen return std::unique_ptr<TargetMachine>( 32*318c69deSSander de Smalen TheTarget->createTargetMachine(TT, CPU, "", TargetOptions(), std::nullopt, 33*318c69deSSander de Smalen std::nullopt, CodeGenOptLevel::Default)); 34*318c69deSSander de Smalen } 35*318c69deSSander de Smalen 36*318c69deSSander de Smalen std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) { 37*318c69deSSander de Smalen AArch64Subtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()), 38*318c69deSSander de Smalen std::string(TM->getTargetCPU()), 39*318c69deSSander de Smalen std::string(TM->getTargetFeatureString()), *TM, true); 40*318c69deSSander de Smalen return std::make_unique<AArch64InstrInfo>(ST); 41*318c69deSSander de Smalen } 42*318c69deSSander de Smalen 43*318c69deSSander de Smalen TEST(AArch64LaneBitmasks, SubRegs) { 44*318c69deSSander de Smalen std::unique_ptr<TargetMachine> TM = createTargetMachine(""); 45*318c69deSSander de Smalen ASSERT_TRUE(TM); 46*318c69deSSander de Smalen 47*318c69deSSander de Smalen std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 48*318c69deSSander de Smalen ASSERT_TRUE(II); 49*318c69deSSander de Smalen 50*318c69deSSander de Smalen const AArch64RegisterInfo &TRI = II->getRegisterInfo(); 51*318c69deSSander de Smalen 52*318c69deSSander de Smalen // Test that the lane masks for the subregisters 'bsub, hsub, ssub, etc' 53*318c69deSSander de Smalen // are composed correctly. 54*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::bsub) | 55*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::bsub_hi), 56*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::hsub)); 57*318c69deSSander de Smalen 58*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::hsub) | 59*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::hsub_hi), 60*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::ssub)); 61*318c69deSSander de Smalen 62*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::ssub) | 63*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::ssub_hi), 64*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub)); 65*318c69deSSander de Smalen 66*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub) | 67*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub_hi), 68*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub)); 69*318c69deSSander de Smalen 70*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::zsub) | 71*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub_hi), 72*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub0)); 73*318c69deSSander de Smalen 74*318c69deSSander de Smalen // Test that the lane masks for tuples are composed correctly. 75*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_bsub) | 76*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_bsub_hi), 77*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub)); 78*318c69deSSander de Smalen 79*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub) | 80*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub_hi), 81*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub)); 82*318c69deSSander de Smalen 83*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub) | 84*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub_hi), 85*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1)); 86*318c69deSSander de Smalen 87*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1) | 88*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::qsub1_then_dsub_hi), 89*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::qsub1)); 90*318c69deSSander de Smalen 91*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sub_32) | 92*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::sub_32_hi), 93*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::sube64)); 94*318c69deSSander de Smalen 95*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::subo64_then_sub_32) | 96*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::subo64_then_sub_32_hi), 97*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::subo64)); 98*318c69deSSander de Smalen 99*318c69deSSander de Smalen // Test that there is no overlap between different (sub)registers 100*318c69deSSander de Smalen // in a tuple. 101*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub0) & 102*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub1) & 103*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub2) & 104*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::dsub3), 105*318c69deSSander de Smalen LaneBitmask::getNone()); 106*318c69deSSander de Smalen 107*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::qsub0) & 108*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::qsub1) & 109*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::qsub2) & 110*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::qsub3), 111*318c69deSSander de Smalen LaneBitmask::getNone()); 112*318c69deSSander de Smalen 113*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::zsub0) & 114*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub1) & 115*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub2) & 116*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::zsub3), 117*318c69deSSander de Smalen LaneBitmask::getNone()); 118*318c69deSSander de Smalen 119*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sube32) & 120*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::subo32), 121*318c69deSSander de Smalen LaneBitmask::getNone()); 122*318c69deSSander de Smalen 123*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sube64) & 124*318c69deSSander de Smalen TRI.getSubRegIndexLaneMask(AArch64::subo64), 125*318c69deSSander de Smalen LaneBitmask::getNone()); 126*318c69deSSander de Smalen 127*318c69deSSander de Smalen // Test that getting a subregister results in the expected subregister. 128*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::bsub), AArch64::B0); 129*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::hsub), AArch64::H0); 130*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::ssub), AArch64::S0); 131*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub), AArch64::D0); 132*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub), AArch64::Q0); 133*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub0), AArch64::Z0); 134*318c69deSSander de Smalen 135*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_bsub), 136*318c69deSSander de Smalen AArch64::B8); 137*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_hsub), 138*318c69deSSander de Smalen AArch64::H8); 139*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_ssub), 140*318c69deSSander de Smalen AArch64::S8); 141*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1), AArch64::D8); 142*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::qsub1), AArch64::Q8); 143*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub1), AArch64::Z8); 144*318c69deSSander de Smalen 145*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::sube64), AArch64::X0); 146*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::subo64), AArch64::X1); 147*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::sub_32), AArch64::W0); 148*318c69deSSander de Smalen EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::subo64_then_sub_32), 149*318c69deSSander de Smalen AArch64::W1); 150*318c69deSSander de Smalen } 151*318c69deSSander de Smalen 152*318c69deSSander de Smalen } // namespace 153