Index: llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp =================================================================== --- llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp +++ llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp @@ -29,6 +29,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/ReachingDefAnalysis.h" #include "llvm/MC/MCInstrDesc.h" +#include "Utils/MVEOpcodes.h" using namespace llvm; @@ -129,21 +130,7 @@ bool IsDo = Start->getOpcode() == ARM::t2DoLoopStart; if (!IsTailPredicationLegal()) return IsDo ? ARM::t2DLS : ARM::t2WLS; - - switch (VCTP->getOpcode()) { - default: - llvm_unreachable("unhandled vctp opcode"); - break; - case ARM::MVE_VCTP8: - return IsDo ? ARM::MVE_DLSTP_8 : ARM::MVE_WLSTP_8; - case ARM::MVE_VCTP16: - return IsDo ? ARM::MVE_DLSTP_16 : ARM::MVE_WLSTP_16; - case ARM::MVE_VCTP32: - return IsDo ? ARM::MVE_DLSTP_32 : ARM::MVE_WLSTP_32; - case ARM::MVE_VCTP64: - return IsDo ? ARM::MVE_DLSTP_64 : ARM::MVE_WLSTP_64; - } - return 0; + return MVEOpcodes::getVCTPLowOverheadLoop(VCTP->getOpcode(), IsDo); } void dump() const { @@ -218,24 +205,6 @@ INITIALIZE_PASS(ARMLowOverheadLoops, DEBUG_TYPE, ARM_LOW_OVERHEAD_LOOPS_NAME, false, false) -static bool IsLoopStart(MachineInstr &MI) { - return MI.getOpcode() == ARM::t2DoLoopStart || - MI.getOpcode() == ARM::t2WhileLoopStart; -} - -static bool IsVCTP(MachineInstr *MI) { - switch (MI->getOpcode()) { - default: - break; - case ARM::MVE_VCTP8: - case ARM::MVE_VCTP16: - case ARM::MVE_VCTP32: - case ARM::MVE_VCTP64: - return true; - } - return false; -} - MachineInstr *LowOverheadLoop::IsSafeToDefineLR(ReachingDefAnalysis *RDA) { // We can define LR because LR already contains the same value. if (Start->getOperand(0).getReg() == ARM::LR) @@ -423,7 +392,7 @@ std::function SearchForStart = [&SearchForStart](MachineBasicBlock *MBB) -> MachineInstr* { for (auto &MI : *MBB) { - if (IsLoopStart(MI)) + if (MVEOpcodes::IsLoopStart(MI.getOpcode())) return &MI; } if (MBB->pred_size() == 1) @@ -451,9 +420,9 @@ LoLoop.Dec = &MI; else if (MI.getOpcode() == ARM::t2LoopEnd) LoLoop.End = &MI; - else if (IsLoopStart(MI)) + else if (MVEOpcodes::IsLoopStart(MI.getOpcode())) LoLoop.Start = &MI; - else if (IsVCTP(&MI)) + else if (MVEOpcodes::IsVCTP(MI.getOpcode())) LoLoop.addVCTP(&MI); else if (MI.getDesc().isCall()) { // TODO: Though the call will require LE to execute again, does this @@ -789,7 +758,7 @@ SmallVector Ends; for (auto &I : MBB) { - if (IsLoopStart(I)) + if (MVEOpcodes::IsLoopStart(I.getOpcode())) Starts.push_back(&I); else if (I.getOpcode() == ARM::t2LoopDec) Decs.push_back(&I); Index: llvm/lib/Target/ARM/MVETailPredication.cpp =================================================================== --- llvm/lib/Target/ARM/MVETailPredication.cpp +++ llvm/lib/Target/ARM/MVETailPredication.cpp @@ -36,6 +36,7 @@ #include "llvm/IR/PatternMatch.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "Utils/MVEOpcodes.h" using namespace llvm; @@ -482,20 +483,8 @@ Builder.SetInsertPoint(cast(Predicate)); ConstantInt *Factor = ConstantInt::get(cast(Ty), VecTy->getNumElements()); - Intrinsic::ID VCTPID; - switch (VecTy->getNumElements()) { - default: - llvm_unreachable("unexpected number of lanes"); - case 4: VCTPID = Intrinsic::arm_mve_vctp32; break; - case 8: VCTPID = Intrinsic::arm_mve_vctp16; break; - case 16: VCTPID = Intrinsic::arm_mve_vctp8; break; - - // FIXME: vctp64 currently not supported because the predicate - // vector wants to be <2 x i1>, but v2i1 is not a legal MVE - // type, so problems happen at isel time. - // Intrinsic::arm_mve_vctp64 exists for ACLE intrinsics - // purposes, but takes a v4i1 instead of a v2i1. - } + + Intrinsic::ID VCTPID = MVEOpcodes::getVCTPInstricID(VecTy->getNumElements()); Function *VCTP = Intrinsic::getDeclaration(M, VCTPID); Value *TailPredicate = Builder.CreateCall(VCTP, Processed); Predicate->replaceAllUsesWith(TailPredicate); Index: llvm/lib/Target/ARM/MVEVPTBlockPass.cpp =================================================================== --- llvm/lib/Target/ARM/MVEVPTBlockPass.cpp +++ llvm/lib/Target/ARM/MVEVPTBlockPass.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/Debug.h" +#include "Utils/MVEOpcodes.h" #include #include @@ -89,59 +90,6 @@ TETE = 15 // 0b1111 }; -static unsigned VCMPOpcodeToVPT(unsigned Opcode) { - switch (Opcode) { - case ARM::MVE_VCMPf32: - return ARM::MVE_VPTv4f32; - case ARM::MVE_VCMPf16: - return ARM::MVE_VPTv8f16; - case ARM::MVE_VCMPi8: - return ARM::MVE_VPTv16i8; - case ARM::MVE_VCMPi16: - return ARM::MVE_VPTv8i16; - case ARM::MVE_VCMPi32: - return ARM::MVE_VPTv4i32; - case ARM::MVE_VCMPu8: - return ARM::MVE_VPTv16u8; - case ARM::MVE_VCMPu16: - return ARM::MVE_VPTv8u16; - case ARM::MVE_VCMPu32: - return ARM::MVE_VPTv4u32; - case ARM::MVE_VCMPs8: - return ARM::MVE_VPTv16s8; - case ARM::MVE_VCMPs16: - return ARM::MVE_VPTv8s16; - case ARM::MVE_VCMPs32: - return ARM::MVE_VPTv4s32; - - case ARM::MVE_VCMPf32r: - return ARM::MVE_VPTv4f32r; - case ARM::MVE_VCMPf16r: - return ARM::MVE_VPTv8f16r; - case ARM::MVE_VCMPi8r: - return ARM::MVE_VPTv16i8r; - case ARM::MVE_VCMPi16r: - return ARM::MVE_VPTv8i16r; - case ARM::MVE_VCMPi32r: - return ARM::MVE_VPTv4i32r; - case ARM::MVE_VCMPu8r: - return ARM::MVE_VPTv16u8r; - case ARM::MVE_VCMPu16r: - return ARM::MVE_VPTv8u16r; - case ARM::MVE_VCMPu32r: - return ARM::MVE_VPTv4u32r; - case ARM::MVE_VCMPs8r: - return ARM::MVE_VPTv16s8r; - case ARM::MVE_VCMPs16r: - return ARM::MVE_VPTv8s16r; - case ARM::MVE_VCMPs32r: - return ARM::MVE_VPTv4s32r; - - default: - return 0; - } -} - static MachineInstr *findVCMPToFoldIntoVPST(MachineInstr *MI, ReachingDefAnalysis *RDA, unsigned &NewOpcode) { @@ -151,7 +99,7 @@ return nullptr; // Now check that Def is a VCMP - if (!(NewOpcode = VCMPOpcodeToVPT(Def->getOpcode()))) + if (!(NewOpcode = MVEOpcodes::VCMPOpcodeToVPT(Def->getOpcode()))) return nullptr; // Check that Def's operands are not defined between the VCMP and MI, i.e. Index: llvm/lib/Target/ARM/Utils/CMakeLists.txt =================================================================== --- llvm/lib/Target/ARM/Utils/CMakeLists.txt +++ llvm/lib/Target/ARM/Utils/CMakeLists.txt @@ -1,3 +1,4 @@ add_llvm_component_library(LLVMARMUtils ARMBaseInfo.cpp + MVEOpcodes.cpp ) Index: llvm/lib/Target/ARM/Utils/MVEOpcodes.h =================================================================== --- /dev/null +++ llvm/lib/Target/ARM/Utils/MVEOpcodes.h @@ -0,0 +1,19 @@ +//===-- MVEOpcodes.h- MVE utilities to query MVE instructions -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +namespace llvm { +namespace MVEOpcodes { + +Intrinsic::ID getVCTPInstricID(int NumElements); +unsigned VCMPOpcodeToVPT(unsigned Opcode); +unsigned getVCTPLowOverheadLoop(unsigned Opcode, bool IsDoLoop); +bool IsVCTP(unsigned Opcode); +bool IsLoopStart(unsigned Opcode); + +} // MVEOpcodes +} // llvm Index: llvm/lib/Target/ARM/Utils/MVEOpcodes.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/ARM/Utils/MVEOpcodes.cpp @@ -0,0 +1,121 @@ +//===-- MVEOpcodes.cpp - MVE utilities to query MVE instructions ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Thumb2InstrInfo.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicsARM.h" + +using namespace llvm; +namespace llvm { +namespace MVEOpcodes { + +Intrinsic::ID getVCTPInstricID(int NumElements) { + switch (NumElements) { + default: + llvm_unreachable("unexpected number of lanes"); + case 4: return Intrinsic::arm_mve_vctp32; + case 8: return Intrinsic::arm_mve_vctp16; + case 16: return Intrinsic::arm_mve_vctp8; + + // FIXME: vctp64 currently not supported because the predicate + // vector wants to be <2 x i1>, but v2i1 is not a legal MVE + // type, so problems happen at isel time. + // Intrinsic::arm_mve_vctp64 exists for ACLE intrinsics + // purposes, but takes a v4i1 instead of a v2i1. + } +} + +unsigned getVCTPLowOverheadLoop(unsigned Opcode, bool IsDoLoop) { + switch (Opcode) { + default: + llvm_unreachable("unhandled vctp opcode"); + break; + case ARM::MVE_VCTP8: + return IsDoLoop ? ARM::MVE_DLSTP_8 : ARM::MVE_WLSTP_8; + case ARM::MVE_VCTP16: + return IsDoLoop ? ARM::MVE_DLSTP_16 : ARM::MVE_WLSTP_16; + case ARM::MVE_VCTP32: + return IsDoLoop ? ARM::MVE_DLSTP_32 : ARM::MVE_WLSTP_32; + case ARM::MVE_VCTP64: + return IsDoLoop ? ARM::MVE_DLSTP_64 : ARM::MVE_WLSTP_64; + } + return 0; +} + +unsigned VCMPOpcodeToVPT(unsigned Opcode) { + switch (Opcode) { + case ARM::MVE_VCMPf32: + return ARM::MVE_VPTv4f32; + case ARM::MVE_VCMPf16: + return ARM::MVE_VPTv8f16; + case ARM::MVE_VCMPi8: + return ARM::MVE_VPTv16i8; + case ARM::MVE_VCMPi16: + return ARM::MVE_VPTv8i16; + case ARM::MVE_VCMPi32: + return ARM::MVE_VPTv4i32; + case ARM::MVE_VCMPu8: + return ARM::MVE_VPTv16u8; + case ARM::MVE_VCMPu16: + return ARM::MVE_VPTv8u16; + case ARM::MVE_VCMPu32: + return ARM::MVE_VPTv4u32; + case ARM::MVE_VCMPs8: + return ARM::MVE_VPTv16s8; + case ARM::MVE_VCMPs16: + return ARM::MVE_VPTv8s16; + case ARM::MVE_VCMPs32: + return ARM::MVE_VPTv4s32; + + case ARM::MVE_VCMPf32r: + return ARM::MVE_VPTv4f32r; + case ARM::MVE_VCMPf16r: + return ARM::MVE_VPTv8f16r; + case ARM::MVE_VCMPi8r: + return ARM::MVE_VPTv16i8r; + case ARM::MVE_VCMPi16r: + return ARM::MVE_VPTv8i16r; + case ARM::MVE_VCMPi32r: + return ARM::MVE_VPTv4i32r; + case ARM::MVE_VCMPu8r: + return ARM::MVE_VPTv16u8r; + case ARM::MVE_VCMPu16r: + return ARM::MVE_VPTv8u16r; + case ARM::MVE_VCMPu32r: + return ARM::MVE_VPTv4u32r; + case ARM::MVE_VCMPs8r: + return ARM::MVE_VPTv16s8r; + case ARM::MVE_VCMPs16r: + return ARM::MVE_VPTv8s16r; + case ARM::MVE_VCMPs32r: + return ARM::MVE_VPTv4s32r; + + default: + return 0; + } +} + +bool IsVCTP(unsigned Opcode) { + switch (Opcode) { + default: break; + case ARM::MVE_VCTP8: + case ARM::MVE_VCTP16: + case ARM::MVE_VCTP32: + case ARM::MVE_VCTP64: + return true; + } + return false; +} + +bool IsLoopStart(unsigned Opcode) { + return Opcode == ARM::t2DoLoopStart || + Opcode == ARM::t2WhileLoopStart; +} + +} // end namespace MVEOpcodes +} // end namespace llvm