#include "AArch64RegisterInfo.h" #include "AArch64InstrInfo.h" #include "AArch64Subtarget.h" #include "AArch64TargetMachine.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "gtest/gtest.h" #define GET_COMPUTE_FEATURES #include "AArch64GenInstrInfo.inc" using namespace llvm; namespace { std::unique_ptr createTargetMachine(const std::string &CPU) { Triple TT("aarch64--"); LLVMInitializeAArch64TargetInfo(); LLVMInitializeAArch64Target(); LLVMInitializeAArch64TargetMC(); std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); return std::unique_ptr( TheTarget->createTargetMachine(TT, CPU, "", TargetOptions(), std::nullopt, std::nullopt, CodeGenOptLevel::Default)); } std::unique_ptr createInstrInfo(TargetMachine *TM) { AArch64Subtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()), std::string(TM->getTargetCPU()), std::string(TM->getTargetFeatureString()), *TM, true); return std::make_unique(ST); } TEST(AArch64LaneBitmasks, SubRegs) { std::unique_ptr TM = createTargetMachine(""); ASSERT_TRUE(TM); std::unique_ptr II = createInstrInfo(TM.get()); ASSERT_TRUE(II); const AArch64RegisterInfo &TRI = II->getRegisterInfo(); // Test that the lane masks for the subregisters 'bsub, hsub, ssub, etc' // are composed correctly. EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::bsub) | TRI.getSubRegIndexLaneMask(AArch64::bsub_hi), TRI.getSubRegIndexLaneMask(AArch64::hsub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::hsub) | TRI.getSubRegIndexLaneMask(AArch64::hsub_hi), TRI.getSubRegIndexLaneMask(AArch64::ssub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::ssub) | TRI.getSubRegIndexLaneMask(AArch64::ssub_hi), TRI.getSubRegIndexLaneMask(AArch64::dsub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub) | TRI.getSubRegIndexLaneMask(AArch64::dsub_hi), TRI.getSubRegIndexLaneMask(AArch64::zsub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::zsub) | TRI.getSubRegIndexLaneMask(AArch64::zsub_hi), TRI.getSubRegIndexLaneMask(AArch64::zsub0)); // Test that the lane masks for tuples are composed correctly. EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_bsub) | TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_bsub_hi), TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub) | TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_hsub_hi), TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub) | TRI.getSubRegIndexLaneMask(AArch64::dsub1_then_ssub_hi), TRI.getSubRegIndexLaneMask(AArch64::dsub1)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub1) | TRI.getSubRegIndexLaneMask(AArch64::qsub1_then_dsub_hi), TRI.getSubRegIndexLaneMask(AArch64::qsub1)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sub_32) | TRI.getSubRegIndexLaneMask(AArch64::sub_32_hi), TRI.getSubRegIndexLaneMask(AArch64::sube64)); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::subo64_then_sub_32) | TRI.getSubRegIndexLaneMask(AArch64::subo64_then_sub_32_hi), TRI.getSubRegIndexLaneMask(AArch64::subo64)); // Test that there is no overlap between different (sub)registers // in a tuple. EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::dsub0) & TRI.getSubRegIndexLaneMask(AArch64::dsub1) & TRI.getSubRegIndexLaneMask(AArch64::dsub2) & TRI.getSubRegIndexLaneMask(AArch64::dsub3), LaneBitmask::getNone()); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::qsub0) & TRI.getSubRegIndexLaneMask(AArch64::qsub1) & TRI.getSubRegIndexLaneMask(AArch64::qsub2) & TRI.getSubRegIndexLaneMask(AArch64::qsub3), LaneBitmask::getNone()); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::zsub0) & TRI.getSubRegIndexLaneMask(AArch64::zsub1) & TRI.getSubRegIndexLaneMask(AArch64::zsub2) & TRI.getSubRegIndexLaneMask(AArch64::zsub3), LaneBitmask::getNone()); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sube32) & TRI.getSubRegIndexLaneMask(AArch64::subo32), LaneBitmask::getNone()); EXPECT_EQ(TRI.getSubRegIndexLaneMask(AArch64::sube64) & TRI.getSubRegIndexLaneMask(AArch64::subo64), LaneBitmask::getNone()); // Test that getting a subregister results in the expected subregister. EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::bsub), AArch64::B0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::hsub), AArch64::H0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::ssub), AArch64::S0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub), AArch64::D0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub), AArch64::Q0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub0), AArch64::Z0); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_bsub), AArch64::B8); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_hsub), AArch64::H8); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1_then_ssub), AArch64::S8); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::dsub1), AArch64::D8); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::qsub1), AArch64::Q8); EXPECT_EQ(TRI.getSubReg(AArch64::Z0_Z8, AArch64::zsub1), AArch64::Z8); EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::sube64), AArch64::X0); EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::subo64), AArch64::X1); EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::sub_32), AArch64::W0); EXPECT_EQ(TRI.getSubReg(AArch64::X0_X1, AArch64::subo64_then_sub_32), AArch64::W1); } } // namespace