@@ -140,3 +140,92 @@ bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI,
140
140
141
141
return false ;
142
142
}
143
+
144
+ bool CombinerHelper::combineMergedBFXCompare (MachineInstr &MI) const {
145
+ const GICmp *Cmp = cast<GICmp>(&MI);
146
+
147
+ ICmpInst::Predicate CC = Cmp->getCond ();
148
+ if (CC != CmpInst::ICMP_EQ && CC != CmpInst::ICMP_NE)
149
+ return false ;
150
+
151
+ Register CmpLHS = Cmp->getLHSReg ();
152
+ Register CmpRHS = Cmp->getRHSReg ();
153
+
154
+ LLT OpTy = MRI.getType (CmpLHS);
155
+ if (!OpTy.isScalar () || OpTy.isPointer ())
156
+ return false ;
157
+
158
+ assert (isZeroOrZeroSplat (CmpRHS, /* AllowUndefs=*/ false ));
159
+
160
+ Register Src;
161
+ const auto IsSrc = [&](Register R) {
162
+ if (!Src) {
163
+ Src = R;
164
+ return true ;
165
+ }
166
+
167
+ return Src == R;
168
+ };
169
+
170
+ MachineInstr *CmpLHSDef = MRI.getVRegDef (CmpLHS);
171
+ if (CmpLHSDef->getOpcode () != TargetOpcode::G_OR)
172
+ return false ;
173
+
174
+ APInt PartsMask (OpTy.getSizeInBits (), 0 );
175
+ SmallVector<MachineInstr *> Worklist = {CmpLHSDef};
176
+ while (!Worklist.empty ()) {
177
+ MachineInstr *Cur = Worklist.pop_back_val ();
178
+
179
+ Register Dst = Cur->getOperand (0 ).getReg ();
180
+ if (!MRI.hasOneUse (Dst) && Dst != Src)
181
+ return false ;
182
+
183
+ if (Cur->getOpcode () == TargetOpcode::G_OR) {
184
+ Worklist.push_back (MRI.getVRegDef (Cur->getOperand (1 ).getReg ()));
185
+ Worklist.push_back (MRI.getVRegDef (Cur->getOperand (2 ).getReg ()));
186
+ continue ;
187
+ }
188
+
189
+ if (Cur->getOpcode () == TargetOpcode::G_UBFX) {
190
+ Register Op = Cur->getOperand (1 ).getReg ();
191
+ Register Width = Cur->getOperand (2 ).getReg ();
192
+ Register Off = Cur->getOperand (3 ).getReg ();
193
+
194
+ auto WidthCst = getIConstantVRegVal (Width, MRI);
195
+ auto OffCst = getIConstantVRegVal (Off, MRI);
196
+ if (!WidthCst || !OffCst || !IsSrc (Op))
197
+ return false ;
198
+
199
+ unsigned Start = OffCst->getZExtValue ();
200
+ unsigned End = Start + WidthCst->getZExtValue ();
201
+ if (End > OpTy.getScalarSizeInBits ())
202
+ return false ;
203
+ PartsMask.setBits (Start, End);
204
+ continue ;
205
+ }
206
+
207
+ if (Cur->getOpcode () == TargetOpcode::G_AND) {
208
+ Register LHS = Cur->getOperand (1 ).getReg ();
209
+ Register RHS = Cur->getOperand (2 ).getReg ();
210
+
211
+ auto MaskCst = getIConstantVRegVal (RHS, MRI);
212
+ if (!MaskCst || !MaskCst->isMask () || !IsSrc (LHS))
213
+ return false ;
214
+
215
+ PartsMask |= *MaskCst;
216
+ continue ;
217
+ }
218
+
219
+ return false ;
220
+ }
221
+
222
+ if (!PartsMask.isMask () || !Src)
223
+ return false ;
224
+
225
+ assert (OpTy == MRI.getType (Src) && " Ignored a type casting operation?" );
226
+ auto MaskedSrc =
227
+ Builder.buildAnd (OpTy, Src, Builder.buildConstant (OpTy, PartsMask));
228
+ Builder.buildICmp (CC, Cmp->getReg (0 ), MaskedSrc, CmpRHS, Cmp->getFlags ());
229
+ MI.eraseFromParent ();
230
+ return true ;
231
+ }
0 commit comments