//===- AArch64ExpandImm.h - AArch64 Immediate Expansion -------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file implements the AArch64ExpandImm stuff. // //===----------------------------------------------------------------------===// #include "AArch64.h" #include "AArch64ExpandImm.h" #include "MCTargetDesc/AArch64AddressingModes.h" usingnamespacellvm; usingnamespacellvm::AArch64_IMM; /// Helper function which extracts the specified 16-bit chunk from a /// 64-bit value. static uint64_t getChunk(uint64_t Imm, unsigned ChunkIdx) { … } /// Check whether the given 16-bit chunk replicated to full 64-bit width /// can be materialized with an ORR instruction. static bool canUseOrr(uint64_t Chunk, uint64_t &Encoding) { … } /// Check for identical 16-bit chunks within the constant and if so /// materialize them with a single ORR instruction. The remaining one or two /// 16-bit chunks will be materialized with MOVK instructions. /// /// This allows us to materialize constants like |A|B|A|A| or |A|B|C|A| (order /// of the chunks doesn't matter), assuming |A|A|A|A| can be materialized with /// an ORR instruction. static bool tryToreplicateChunks(uint64_t UImm, SmallVectorImpl<ImmInsnModel> &Insn) { … } /// Check whether this chunk matches the pattern '1...0...'. This pattern /// starts a contiguous sequence of ones if we look at the bits from the LSB /// towards the MSB. static bool isStartChunk(uint64_t Chunk) { … } /// Check whether this chunk matches the pattern '0...1...' This pattern /// ends a contiguous sequence of ones if we look at the bits from the LSB /// towards the MSB. static bool isEndChunk(uint64_t Chunk) { … } /// Clear or set all bits in the chunk at the given index. static uint64_t updateImm(uint64_t Imm, unsigned Idx, bool Clear) { … } /// Check whether the constant contains a sequence of contiguous ones, /// which might be interrupted by one or two chunks. If so, materialize the /// sequence of contiguous ones with an ORR instruction. /// Materialize the chunks which are either interrupting the sequence or outside /// of the sequence with a MOVK instruction. /// /// Assuming S is a chunk which starts the sequence (1...0...), E is a chunk /// which ends the sequence (0...1...). Then we are looking for constants which /// contain at least one S and E chunk. /// E.g. |E|A|B|S|, |A|E|B|S| or |A|B|E|S|. /// /// We are also looking for constants like |S|A|B|E| where the contiguous /// sequence of ones wraps around the MSB into the LSB. static bool trySequenceOfOnes(uint64_t UImm, SmallVectorImpl<ImmInsnModel> &Insn) { … } static uint64_t GetRunOfOnesStartingAt(uint64_t V, uint64_t StartPosition) { … } static uint64_t MaximallyReplicateSubImmediate(uint64_t V, uint64_t Subset) { … } // Find the logical immediate that covers the most bits in RemainingBits, // allowing for additional bits to be set that were set in OriginalBits. static uint64_t maximalLogicalImmWithin(uint64_t RemainingBits, uint64_t OriginalBits) { … } static std::optional<std::pair<uint64_t, uint64_t>> decomposeIntoOrrOfLogicalImmediates(uint64_t UImm) { … } // Attempt to expand an immediate as the ORR of a pair of logical immediates. static bool tryOrrOfLogicalImmediates(uint64_t UImm, SmallVectorImpl<ImmInsnModel> &Insn) { … } // Attempt to expand an immediate as the AND of a pair of logical immediates. // This is done by applying DeMorgan's law, under which logical immediates // are closed. static bool tryAndOfLogicalImmediates(uint64_t UImm, SmallVectorImpl<ImmInsnModel> &Insn) { … } // Check whether the constant can be represented by exclusive-or of two 64-bit // logical immediates. If so, materialize it with an ORR instruction followed // by an EOR instruction. // // This encoding allows all remaining repeated byte patterns, and many repeated // 16-bit values, to be encoded without needing four instructions. It can also // represent some irregular bitmasks (although those would mostly only need // three instructions otherwise). static bool tryEorOfLogicalImmediates(uint64_t Imm, SmallVectorImpl<ImmInsnModel> &Insn) { … } /// \brief Expand a MOVi32imm or MOVi64imm pseudo instruction to a /// MOVZ or MOVN of width BitSize followed by up to 3 MOVK instructions. static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize, unsigned OneChunks, unsigned ZeroChunks, SmallVectorImpl<ImmInsnModel> &Insn) { … } /// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more /// real move-immediate instructions to synthesize the immediate. void AArch64_IMM::expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl<ImmInsnModel> &Insn) { … }