1212// MOVi64imm + ANDS?Xrr ==> ANDXri + ANDS?Xri
1313//
1414// 2. MOVi32imm + ADDWrr ==> ADDWRi + ADDWRi
15- // MOVi64imm + ADDXrr ==> ANDXri + ANDXri
15+ // MOVi64imm + ADDXrr ==> ADDXri + ADDXri
1616//
1717// 3. MOVi32imm + SUBWrr ==> SUBWRi + SUBWRi
1818// MOVi64imm + SUBXrr ==> SUBXri + SUBXri
@@ -125,8 +125,13 @@ struct AArch64MIPeepholeOpt : public MachineFunctionPass {
125125 template <typename T>
126126 bool visitADDSSUBS (OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI);
127127
128+ // Strategy used to split logical immediate bitmasks.
129+ enum class SplitStrategy {
130+ Intersect,
131+ };
128132 template <typename T>
129- bool visitAND (unsigned Opc, MachineInstr &MI, unsigned OtherOpc = 0 );
133+ bool trySplitLogicalImm (unsigned Opc, MachineInstr &MI,
134+ SplitStrategy Strategy, unsigned OtherOpc = 0 );
130135 bool visitORR (MachineInstr &MI);
131136 bool visitCSEL (MachineInstr &MI);
132137 bool visitINSERT (MachineInstr &MI);
@@ -158,14 +163,6 @@ INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt",
158163template <typename T>
159164static bool splitBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc) {
160165 T UImm = static_cast <T>(Imm);
161- if (AArch64_AM::isLogicalImmediate (UImm, RegSize))
162- return false ;
163-
164- // If this immediate can be handled by one instruction, do not split it.
165- SmallVector<AArch64_IMM::ImmInsnModel, 4 > Insn;
166- AArch64_IMM::expandMOVImm (UImm, RegSize, Insn);
167- if (Insn.size () == 1 )
168- return false ;
169166
170167 // The bitmask immediate consists of consecutive ones. Let's say there is
171168 // constant 0b00000000001000000000010000000000 which does not consist of
@@ -194,8 +191,9 @@ static bool splitBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc) {
194191}
195192
196193template <typename T>
197- bool AArch64MIPeepholeOpt::visitAND (unsigned Opc, MachineInstr &MI,
198- unsigned OtherOpc) {
194+ bool AArch64MIPeepholeOpt::trySplitLogicalImm (unsigned Opc, MachineInstr &MI,
195+ SplitStrategy Strategy,
196+ unsigned OtherOpc) {
199197 // Try below transformation.
200198 //
201199 // MOVi32imm + ANDS?Wrr ==> ANDWri + ANDS?Wri
@@ -208,9 +206,26 @@ bool AArch64MIPeepholeOpt::visitAND(unsigned Opc, MachineInstr &MI,
208206
209207 return splitTwoPartImm<T>(
210208 MI,
211- [Opc, OtherOpc](T Imm, unsigned RegSize, T &Imm0,
212- T &Imm1) -> std::optional<OpcodePair> {
213- if (splitBitmaskImm (Imm, RegSize, Imm0, Imm1))
209+ [Opc, Strategy, OtherOpc](T Imm, unsigned RegSize, T &Imm0,
210+ T &Imm1) -> std::optional<OpcodePair> {
211+ // If this immediate is already a suitable bitmask, don't split it.
212+ // TODO: Should we just combine the two instructions in this case?
213+ if (AArch64_AM::isLogicalImmediate (Imm, RegSize))
214+ return std::nullopt ;
215+
216+ // If this immediate can be handled by one instruction, don't split it.
217+ SmallVector<AArch64_IMM::ImmInsnModel, 4 > Insn;
218+ AArch64_IMM::expandMOVImm (Imm, RegSize, Insn);
219+ if (Insn.size () == 1 )
220+ return std::nullopt ;
221+
222+ bool SplitSucc = false ;
223+ switch (Strategy) {
224+ case SplitStrategy::Intersect:
225+ SplitSucc = splitBitmaskImm (Imm, RegSize, Imm0, Imm1);
226+ break ;
227+ }
228+ if (SplitSucc)
214229 return std::make_pair (Opc, !OtherOpc ? Opc : OtherOpc);
215230 return std::nullopt ;
216231 },
@@ -859,16 +874,20 @@ bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
859874 Changed |= visitINSERT (MI);
860875 break ;
861876 case AArch64::ANDWrr:
862- Changed |= visitAND<uint32_t >(AArch64::ANDWri, MI);
877+ Changed |= trySplitLogicalImm<uint32_t >(AArch64::ANDWri, MI,
878+ SplitStrategy::Intersect);
863879 break ;
864880 case AArch64::ANDXrr:
865- Changed |= visitAND<uint64_t >(AArch64::ANDXri, MI);
881+ Changed |= trySplitLogicalImm<uint64_t >(AArch64::ANDXri, MI,
882+ SplitStrategy::Intersect);
866883 break ;
867884 case AArch64::ANDSWrr:
868- Changed |= visitAND<uint32_t >(AArch64::ANDWri, MI, AArch64::ANDSWri);
885+ Changed |= trySplitLogicalImm<uint32_t >(
886+ AArch64::ANDWri, MI, SplitStrategy::Intersect, AArch64::ANDSWri);
869887 break ;
870888 case AArch64::ANDSXrr:
871- Changed |= visitAND<uint64_t >(AArch64::ANDXri, MI, AArch64::ANDSXri);
889+ Changed |= trySplitLogicalImm<uint64_t >(
890+ AArch64::ANDXri, MI, SplitStrategy::Intersect, AArch64::ANDSXri);
872891 break ;
873892 case AArch64::ORRWrs:
874893 Changed |= visitORR (MI);
0 commit comments