12
12
// MOVi64imm + ANDS?Xrr ==> ANDXri + ANDS?Xri
13
13
//
14
14
// 2. MOVi32imm + ADDWrr ==> ADDWRi + ADDWRi
15
- // MOVi64imm + ADDXrr ==> ANDXri + ANDXri
15
+ // MOVi64imm + ADDXrr ==> ADDXri + ADDXri
16
16
//
17
17
// 3. MOVi32imm + SUBWrr ==> SUBWRi + SUBWRi
18
18
// MOVi64imm + SUBXrr ==> SUBXri + SUBXri
@@ -125,8 +125,13 @@ struct AArch64MIPeepholeOpt : public MachineFunctionPass {
125
125
template <typename T>
126
126
bool visitADDSSUBS (OpcodePair PosOpcs, OpcodePair NegOpcs, MachineInstr &MI);
127
127
128
+ // Strategy used to split logical immediate bitmasks.
129
+ enum class SplitStrategy {
130
+ Intersect,
131
+ };
128
132
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 );
130
135
bool visitORR (MachineInstr &MI);
131
136
bool visitCSEL (MachineInstr &MI);
132
137
bool visitINSERT (MachineInstr &MI);
@@ -158,14 +163,6 @@ INITIALIZE_PASS(AArch64MIPeepholeOpt, "aarch64-mi-peephole-opt",
158
163
template <typename T>
159
164
static bool splitBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc) {
160
165
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 ;
169
166
170
167
// The bitmask immediate consists of consecutive ones. Let's say there is
171
168
// constant 0b00000000001000000000010000000000 which does not consist of
@@ -194,8 +191,9 @@ static bool splitBitmaskImm(T Imm, unsigned RegSize, T &Imm1Enc, T &Imm2Enc) {
194
191
}
195
192
196
193
template <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) {
199
197
// Try below transformation.
200
198
//
201
199
// MOVi32imm + ANDS?Wrr ==> ANDWri + ANDS?Wri
@@ -208,9 +206,26 @@ bool AArch64MIPeepholeOpt::visitAND(unsigned Opc, MachineInstr &MI,
208
206
209
207
return splitTwoPartImm<T>(
210
208
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)
214
229
return std::make_pair (Opc, !OtherOpc ? Opc : OtherOpc);
215
230
return std::nullopt;
216
231
},
@@ -859,16 +874,20 @@ bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
859
874
Changed |= visitINSERT (MI);
860
875
break ;
861
876
case AArch64::ANDWrr:
862
- Changed |= visitAND<uint32_t >(AArch64::ANDWri, MI);
877
+ Changed |= trySplitLogicalImm<uint32_t >(AArch64::ANDWri, MI,
878
+ SplitStrategy::Intersect);
863
879
break ;
864
880
case AArch64::ANDXrr:
865
- Changed |= visitAND<uint64_t >(AArch64::ANDXri, MI);
881
+ Changed |= trySplitLogicalImm<uint64_t >(AArch64::ANDXri, MI,
882
+ SplitStrategy::Intersect);
866
883
break ;
867
884
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);
869
887
break ;
870
888
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);
872
891
break ;
873
892
case AArch64::ORRWrs:
874
893
Changed |= visitORR (MI);
0 commit comments