xref: /llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp (revision ee7ca0dddafb609090ad1789570c099d95c0afb6)
12ca300f9SThorsten Schütt //===- CombinerHelperCasts.cpp---------------------------------------------===//
22ca300f9SThorsten Schütt //
32ca300f9SThorsten Schütt // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42ca300f9SThorsten Schütt // See https://llvm.org/LICENSE.txt for license information.
52ca300f9SThorsten Schütt // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62ca300f9SThorsten Schütt //
72ca300f9SThorsten Schütt //===----------------------------------------------------------------------===//
82ca300f9SThorsten Schütt //
92ca300f9SThorsten Schütt // This file implements CombinerHelper for G_ANYEXT, G_SEXT, G_TRUNC, and
102ca300f9SThorsten Schütt // G_ZEXT
112ca300f9SThorsten Schütt //
122ca300f9SThorsten Schütt //===----------------------------------------------------------------------===//
132ca300f9SThorsten Schütt #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
142ca300f9SThorsten Schütt #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
152ca300f9SThorsten Schütt #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
162ca300f9SThorsten Schütt #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
172ca300f9SThorsten Schütt #include "llvm/CodeGen/GlobalISel/Utils.h"
182ca300f9SThorsten Schütt #include "llvm/CodeGen/LowLevelTypeUtils.h"
192ca300f9SThorsten Schütt #include "llvm/CodeGen/MachineOperand.h"
202ca300f9SThorsten Schütt #include "llvm/CodeGen/MachineRegisterInfo.h"
212ca300f9SThorsten Schütt #include "llvm/CodeGen/TargetOpcodes.h"
222ca300f9SThorsten Schütt #include "llvm/Support/Casting.h"
232ca300f9SThorsten Schütt 
242ca300f9SThorsten Schütt #define DEBUG_TYPE "gi-combiner"
252ca300f9SThorsten Schütt 
262ca300f9SThorsten Schütt using namespace llvm;
272ca300f9SThorsten Schütt 
282ca300f9SThorsten Schütt bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
29*ee7ca0ddSPaul Bowen-Huggett                                       BuildFnTy &MatchInfo) const {
302ca300f9SThorsten Schütt   GSext *Sext = cast<GSext>(getDefIgnoringCopies(MO.getReg(), MRI));
312ca300f9SThorsten Schütt   GTrunc *Trunc = cast<GTrunc>(getDefIgnoringCopies(Sext->getSrcReg(), MRI));
322ca300f9SThorsten Schütt 
332ca300f9SThorsten Schütt   Register Dst = Sext->getReg(0);
342ca300f9SThorsten Schütt   Register Src = Trunc->getSrcReg();
352ca300f9SThorsten Schütt 
362ca300f9SThorsten Schütt   LLT DstTy = MRI.getType(Dst);
372ca300f9SThorsten Schütt   LLT SrcTy = MRI.getType(Src);
382ca300f9SThorsten Schütt 
392ca300f9SThorsten Schütt   if (DstTy == SrcTy) {
402ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
412ca300f9SThorsten Schütt     return true;
422ca300f9SThorsten Schütt   }
432ca300f9SThorsten Schütt 
442ca300f9SThorsten Schütt   if (DstTy.getScalarSizeInBits() < SrcTy.getScalarSizeInBits() &&
452ca300f9SThorsten Schütt       isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) {
462ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) {
472ca300f9SThorsten Schütt       B.buildTrunc(Dst, Src, MachineInstr::MIFlag::NoSWrap);
482ca300f9SThorsten Schütt     };
492ca300f9SThorsten Schütt     return true;
502ca300f9SThorsten Schütt   }
512ca300f9SThorsten Schütt 
522ca300f9SThorsten Schütt   if (DstTy.getScalarSizeInBits() > SrcTy.getScalarSizeInBits() &&
532ca300f9SThorsten Schütt       isLegalOrBeforeLegalizer({TargetOpcode::G_SEXT, {DstTy, SrcTy}})) {
542ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
552ca300f9SThorsten Schütt     return true;
562ca300f9SThorsten Schütt   }
572ca300f9SThorsten Schütt 
582ca300f9SThorsten Schütt   return false;
592ca300f9SThorsten Schütt }
602ca300f9SThorsten Schütt 
612ca300f9SThorsten Schütt bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
62*ee7ca0ddSPaul Bowen-Huggett                                       BuildFnTy &MatchInfo) const {
632ca300f9SThorsten Schütt   GZext *Zext = cast<GZext>(getDefIgnoringCopies(MO.getReg(), MRI));
642ca300f9SThorsten Schütt   GTrunc *Trunc = cast<GTrunc>(getDefIgnoringCopies(Zext->getSrcReg(), MRI));
652ca300f9SThorsten Schütt 
662ca300f9SThorsten Schütt   Register Dst = Zext->getReg(0);
672ca300f9SThorsten Schütt   Register Src = Trunc->getSrcReg();
682ca300f9SThorsten Schütt 
692ca300f9SThorsten Schütt   LLT DstTy = MRI.getType(Dst);
702ca300f9SThorsten Schütt   LLT SrcTy = MRI.getType(Src);
712ca300f9SThorsten Schütt 
722ca300f9SThorsten Schütt   if (DstTy == SrcTy) {
732ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
742ca300f9SThorsten Schütt     return true;
752ca300f9SThorsten Schütt   }
762ca300f9SThorsten Schütt 
772ca300f9SThorsten Schütt   if (DstTy.getScalarSizeInBits() < SrcTy.getScalarSizeInBits() &&
782ca300f9SThorsten Schütt       isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) {
792ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) {
802ca300f9SThorsten Schütt       B.buildTrunc(Dst, Src, MachineInstr::MIFlag::NoUWrap);
812ca300f9SThorsten Schütt     };
822ca300f9SThorsten Schütt     return true;
832ca300f9SThorsten Schütt   }
842ca300f9SThorsten Schütt 
852ca300f9SThorsten Schütt   if (DstTy.getScalarSizeInBits() > SrcTy.getScalarSizeInBits() &&
862ca300f9SThorsten Schütt       isLegalOrBeforeLegalizer({TargetOpcode::G_ZEXT, {DstTy, SrcTy}})) {
872ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) {
882ca300f9SThorsten Schütt       B.buildZExt(Dst, Src, MachineInstr::MIFlag::NonNeg);
892ca300f9SThorsten Schütt     };
902ca300f9SThorsten Schütt     return true;
912ca300f9SThorsten Schütt   }
922ca300f9SThorsten Schütt 
932ca300f9SThorsten Schütt   return false;
942ca300f9SThorsten Schütt }
952ca300f9SThorsten Schütt 
962ca300f9SThorsten Schütt bool CombinerHelper::matchNonNegZext(const MachineOperand &MO,
97*ee7ca0ddSPaul Bowen-Huggett                                      BuildFnTy &MatchInfo) const {
982ca300f9SThorsten Schütt   GZext *Zext = cast<GZext>(MRI.getVRegDef(MO.getReg()));
992ca300f9SThorsten Schütt 
1002ca300f9SThorsten Schütt   Register Dst = Zext->getReg(0);
1012ca300f9SThorsten Schütt   Register Src = Zext->getSrcReg();
1022ca300f9SThorsten Schütt 
1032ca300f9SThorsten Schütt   LLT DstTy = MRI.getType(Dst);
1042ca300f9SThorsten Schütt   LLT SrcTy = MRI.getType(Src);
1052ca300f9SThorsten Schütt   const auto &TLI = getTargetLowering();
1062ca300f9SThorsten Schütt 
1072ca300f9SThorsten Schütt   // Convert zext nneg to sext if sext is the preferred form for the target.
1082ca300f9SThorsten Schütt   if (isLegalOrBeforeLegalizer({TargetOpcode::G_SEXT, {DstTy, SrcTy}}) &&
1092ca300f9SThorsten Schütt       TLI.isSExtCheaperThanZExt(getMVTForLLT(SrcTy), getMVTForLLT(DstTy))) {
1102ca300f9SThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
1112ca300f9SThorsten Schütt     return true;
1122ca300f9SThorsten Schütt   }
1132ca300f9SThorsten Schütt 
1142ca300f9SThorsten Schütt   return false;
1152ca300f9SThorsten Schütt }
116bfcfb0fdSThorsten Schütt 
117bfcfb0fdSThorsten Schütt bool CombinerHelper::matchTruncateOfExt(const MachineInstr &Root,
118bfcfb0fdSThorsten Schütt                                         const MachineInstr &ExtMI,
119*ee7ca0ddSPaul Bowen-Huggett                                         BuildFnTy &MatchInfo) const {
120bfcfb0fdSThorsten Schütt   const GTrunc *Trunc = cast<GTrunc>(&Root);
121bfcfb0fdSThorsten Schütt   const GExtOp *Ext = cast<GExtOp>(&ExtMI);
122bfcfb0fdSThorsten Schütt 
123bfcfb0fdSThorsten Schütt   if (!MRI.hasOneNonDBGUse(Ext->getReg(0)))
124bfcfb0fdSThorsten Schütt     return false;
125bfcfb0fdSThorsten Schütt 
126bfcfb0fdSThorsten Schütt   Register Dst = Trunc->getReg(0);
127bfcfb0fdSThorsten Schütt   Register Src = Ext->getSrcReg();
128bfcfb0fdSThorsten Schütt   LLT DstTy = MRI.getType(Dst);
129bfcfb0fdSThorsten Schütt   LLT SrcTy = MRI.getType(Src);
130bfcfb0fdSThorsten Schütt 
131bfcfb0fdSThorsten Schütt   if (SrcTy == DstTy) {
132bfcfb0fdSThorsten Schütt     // The source and the destination are equally sized. We need to copy.
133bfcfb0fdSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
134bfcfb0fdSThorsten Schütt 
135bfcfb0fdSThorsten Schütt     return true;
136bfcfb0fdSThorsten Schütt   }
137bfcfb0fdSThorsten Schütt 
138bfcfb0fdSThorsten Schütt   if (SrcTy.getScalarSizeInBits() < DstTy.getScalarSizeInBits()) {
139bfcfb0fdSThorsten Schütt     // If the source is smaller than the destination, we need to extend.
140bfcfb0fdSThorsten Schütt 
141bfcfb0fdSThorsten Schütt     if (!isLegalOrBeforeLegalizer({Ext->getOpcode(), {DstTy, SrcTy}}))
142bfcfb0fdSThorsten Schütt       return false;
143bfcfb0fdSThorsten Schütt 
144bfcfb0fdSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) {
145bfcfb0fdSThorsten Schütt       B.buildInstr(Ext->getOpcode(), {Dst}, {Src});
146bfcfb0fdSThorsten Schütt     };
147bfcfb0fdSThorsten Schütt 
148bfcfb0fdSThorsten Schütt     return true;
149bfcfb0fdSThorsten Schütt   }
150bfcfb0fdSThorsten Schütt 
151bfcfb0fdSThorsten Schütt   if (SrcTy.getScalarSizeInBits() > DstTy.getScalarSizeInBits()) {
152bfcfb0fdSThorsten Schütt     // If the source is larger than the destination, then we need to truncate.
153bfcfb0fdSThorsten Schütt 
154bfcfb0fdSThorsten Schütt     if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}}))
155bfcfb0fdSThorsten Schütt       return false;
156bfcfb0fdSThorsten Schütt 
157bfcfb0fdSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildTrunc(Dst, Src); };
158bfcfb0fdSThorsten Schütt 
159bfcfb0fdSThorsten Schütt     return true;
160bfcfb0fdSThorsten Schütt   }
161bfcfb0fdSThorsten Schütt 
162bfcfb0fdSThorsten Schütt   return false;
163bfcfb0fdSThorsten Schütt }
164db8c84fcSThorsten Schütt 
165db8c84fcSThorsten Schütt bool CombinerHelper::isCastFree(unsigned Opcode, LLT ToTy, LLT FromTy) const {
166db8c84fcSThorsten Schütt   const TargetLowering &TLI = getTargetLowering();
167db8c84fcSThorsten Schütt   LLVMContext &Ctx = getContext();
168db8c84fcSThorsten Schütt 
169db8c84fcSThorsten Schütt   switch (Opcode) {
170db8c84fcSThorsten Schütt   case TargetOpcode::G_ANYEXT:
171db8c84fcSThorsten Schütt   case TargetOpcode::G_ZEXT:
1720d9fc174SCraig Topper     return TLI.isZExtFree(FromTy, ToTy, Ctx);
173db8c84fcSThorsten Schütt   case TargetOpcode::G_TRUNC:
1740d9fc174SCraig Topper     return TLI.isTruncateFree(FromTy, ToTy, Ctx);
175db8c84fcSThorsten Schütt   default:
176db8c84fcSThorsten Schütt     return false;
177db8c84fcSThorsten Schütt   }
178db8c84fcSThorsten Schütt }
179db8c84fcSThorsten Schütt 
180db8c84fcSThorsten Schütt bool CombinerHelper::matchCastOfSelect(const MachineInstr &CastMI,
181db8c84fcSThorsten Schütt                                        const MachineInstr &SelectMI,
182*ee7ca0ddSPaul Bowen-Huggett                                        BuildFnTy &MatchInfo) const {
183db8c84fcSThorsten Schütt   const GExtOrTruncOp *Cast = cast<GExtOrTruncOp>(&CastMI);
184db8c84fcSThorsten Schütt   const GSelect *Select = cast<GSelect>(&SelectMI);
185db8c84fcSThorsten Schütt 
186db8c84fcSThorsten Schütt   if (!MRI.hasOneNonDBGUse(Select->getReg(0)))
187db8c84fcSThorsten Schütt     return false;
188db8c84fcSThorsten Schütt 
189db8c84fcSThorsten Schütt   Register Dst = Cast->getReg(0);
190db8c84fcSThorsten Schütt   LLT DstTy = MRI.getType(Dst);
191db8c84fcSThorsten Schütt   LLT CondTy = MRI.getType(Select->getCondReg());
192db8c84fcSThorsten Schütt   Register TrueReg = Select->getTrueReg();
193db8c84fcSThorsten Schütt   Register FalseReg = Select->getFalseReg();
194db8c84fcSThorsten Schütt   LLT SrcTy = MRI.getType(TrueReg);
195db8c84fcSThorsten Schütt   Register Cond = Select->getCondReg();
196db8c84fcSThorsten Schütt 
197db8c84fcSThorsten Schütt   if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SELECT, {DstTy, CondTy}}))
198db8c84fcSThorsten Schütt     return false;
199db8c84fcSThorsten Schütt 
200db8c84fcSThorsten Schütt   if (!isCastFree(Cast->getOpcode(), DstTy, SrcTy))
201db8c84fcSThorsten Schütt     return false;
202db8c84fcSThorsten Schütt 
203db8c84fcSThorsten Schütt   MatchInfo = [=](MachineIRBuilder &B) {
204db8c84fcSThorsten Schütt     auto True = B.buildInstr(Cast->getOpcode(), {DstTy}, {TrueReg});
205db8c84fcSThorsten Schütt     auto False = B.buildInstr(Cast->getOpcode(), {DstTy}, {FalseReg});
206db8c84fcSThorsten Schütt     B.buildSelect(Dst, Cond, True, False);
207db8c84fcSThorsten Schütt   };
208db8c84fcSThorsten Schütt 
209db8c84fcSThorsten Schütt   return true;
210db8c84fcSThorsten Schütt }
211710a552dSThorsten Schütt 
212710a552dSThorsten Schütt bool CombinerHelper::matchExtOfExt(const MachineInstr &FirstMI,
213710a552dSThorsten Schütt                                    const MachineInstr &SecondMI,
214*ee7ca0ddSPaul Bowen-Huggett                                    BuildFnTy &MatchInfo) const {
215710a552dSThorsten Schütt   const GExtOp *First = cast<GExtOp>(&FirstMI);
216710a552dSThorsten Schütt   const GExtOp *Second = cast<GExtOp>(&SecondMI);
217710a552dSThorsten Schütt 
218710a552dSThorsten Schütt   Register Dst = First->getReg(0);
219710a552dSThorsten Schütt   Register Src = Second->getSrcReg();
220710a552dSThorsten Schütt   LLT DstTy = MRI.getType(Dst);
221710a552dSThorsten Schütt   LLT SrcTy = MRI.getType(Src);
222710a552dSThorsten Schütt 
223710a552dSThorsten Schütt   if (!MRI.hasOneNonDBGUse(Second->getReg(0)))
224710a552dSThorsten Schütt     return false;
225710a552dSThorsten Schütt 
226710a552dSThorsten Schütt   // ext of ext -> later ext
227710a552dSThorsten Schütt   if (First->getOpcode() == Second->getOpcode() &&
228710a552dSThorsten Schütt       isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
229710a552dSThorsten Schütt     if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
230710a552dSThorsten Schütt       MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
231710a552dSThorsten Schütt       if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
232710a552dSThorsten Schütt         Flag = MachineInstr::MIFlag::NonNeg;
233710a552dSThorsten Schütt       MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
234710a552dSThorsten Schütt       return true;
235710a552dSThorsten Schütt     }
236710a552dSThorsten Schütt     // not zext -> no flags
237710a552dSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) {
238710a552dSThorsten Schütt       B.buildInstr(Second->getOpcode(), {Dst}, {Src});
239710a552dSThorsten Schütt     };
240710a552dSThorsten Schütt     return true;
241710a552dSThorsten Schütt   }
242710a552dSThorsten Schütt 
243710a552dSThorsten Schütt   // anyext of sext/zext  -> sext/zext
244710a552dSThorsten Schütt   // -> pick anyext as second ext, then ext of ext
245710a552dSThorsten Schütt   if (First->getOpcode() == TargetOpcode::G_ANYEXT &&
246710a552dSThorsten Schütt       isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
247710a552dSThorsten Schütt     if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
248710a552dSThorsten Schütt       MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
249710a552dSThorsten Schütt       if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
250710a552dSThorsten Schütt         Flag = MachineInstr::MIFlag::NonNeg;
251710a552dSThorsten Schütt       MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
252710a552dSThorsten Schütt       return true;
253710a552dSThorsten Schütt     }
254710a552dSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
255710a552dSThorsten Schütt     return true;
256710a552dSThorsten Schütt   }
257710a552dSThorsten Schütt 
258710a552dSThorsten Schütt   // sext/zext of anyext -> sext/zext
259710a552dSThorsten Schütt   // -> pick anyext as first ext, then ext of ext
260710a552dSThorsten Schütt   if (Second->getOpcode() == TargetOpcode::G_ANYEXT &&
261710a552dSThorsten Schütt       isLegalOrBeforeLegalizer({First->getOpcode(), {DstTy, SrcTy}})) {
262710a552dSThorsten Schütt     if (First->getOpcode() == TargetOpcode::G_ZEXT) {
263710a552dSThorsten Schütt       MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
264710a552dSThorsten Schütt       if (First->getFlag(MachineInstr::MIFlag::NonNeg))
265710a552dSThorsten Schütt         Flag = MachineInstr::MIFlag::NonNeg;
266710a552dSThorsten Schütt       MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
267710a552dSThorsten Schütt       return true;
268710a552dSThorsten Schütt     }
269710a552dSThorsten Schütt     MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
270710a552dSThorsten Schütt     return true;
271710a552dSThorsten Schütt   }
272710a552dSThorsten Schütt 
273710a552dSThorsten Schütt   return false;
274710a552dSThorsten Schütt }
2750b0ccd56SThorsten Schütt 
2760b0ccd56SThorsten Schütt bool CombinerHelper::matchCastOfBuildVector(const MachineInstr &CastMI,
2770b0ccd56SThorsten Schütt                                             const MachineInstr &BVMI,
278*ee7ca0ddSPaul Bowen-Huggett                                             BuildFnTy &MatchInfo) const {
2790b0ccd56SThorsten Schütt   const GExtOrTruncOp *Cast = cast<GExtOrTruncOp>(&CastMI);
2800b0ccd56SThorsten Schütt   const GBuildVector *BV = cast<GBuildVector>(&BVMI);
2810b0ccd56SThorsten Schütt 
2820b0ccd56SThorsten Schütt   if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
2830b0ccd56SThorsten Schütt     return false;
2840b0ccd56SThorsten Schütt 
2850b0ccd56SThorsten Schütt   Register Dst = Cast->getReg(0);
2860b0ccd56SThorsten Schütt   // The type of the new build vector.
2870b0ccd56SThorsten Schütt   LLT DstTy = MRI.getType(Dst);
2880b0ccd56SThorsten Schütt   // The scalar or element type of the new build vector.
2890b0ccd56SThorsten Schütt   LLT ElemTy = DstTy.getScalarType();
2900b0ccd56SThorsten Schütt   // The scalar or element type of the old build vector.
2910b0ccd56SThorsten Schütt   LLT InputElemTy = MRI.getType(BV->getReg(0)).getElementType();
2920b0ccd56SThorsten Schütt 
2930b0ccd56SThorsten Schütt   // Check legality of new build vector, the scalar casts, and profitability of
2940b0ccd56SThorsten Schütt   // the many casts.
2950b0ccd56SThorsten Schütt   if (!isLegalOrBeforeLegalizer(
2960b0ccd56SThorsten Schütt           {TargetOpcode::G_BUILD_VECTOR, {DstTy, ElemTy}}) ||
2970b0ccd56SThorsten Schütt       !isLegalOrBeforeLegalizer({Cast->getOpcode(), {ElemTy, InputElemTy}}) ||
2980b0ccd56SThorsten Schütt       !isCastFree(Cast->getOpcode(), ElemTy, InputElemTy))
2990b0ccd56SThorsten Schütt     return false;
3000b0ccd56SThorsten Schütt 
3010b0ccd56SThorsten Schütt   MatchInfo = [=](MachineIRBuilder &B) {
3020b0ccd56SThorsten Schütt     SmallVector<Register> Casts;
3030b0ccd56SThorsten Schütt     unsigned Elements = BV->getNumSources();
3040b0ccd56SThorsten Schütt     for (unsigned I = 0; I < Elements; ++I) {
3050b0ccd56SThorsten Schütt       auto CastI =
3060b0ccd56SThorsten Schütt           B.buildInstr(Cast->getOpcode(), {ElemTy}, {BV->getSourceReg(I)});
3070b0ccd56SThorsten Schütt       Casts.push_back(CastI.getReg(0));
3080b0ccd56SThorsten Schütt     }
3090b0ccd56SThorsten Schütt 
3100b0ccd56SThorsten Schütt     B.buildBuildVector(Dst, Casts);
3110b0ccd56SThorsten Schütt   };
3120b0ccd56SThorsten Schütt 
3130b0ccd56SThorsten Schütt   return true;
3140b0ccd56SThorsten Schütt }
315ba4bcce5SThorsten Schütt 
316ba4bcce5SThorsten Schütt bool CombinerHelper::matchNarrowBinop(const MachineInstr &TruncMI,
317ba4bcce5SThorsten Schütt                                       const MachineInstr &BinopMI,
318*ee7ca0ddSPaul Bowen-Huggett                                       BuildFnTy &MatchInfo) const {
319ba4bcce5SThorsten Schütt   const GTrunc *Trunc = cast<GTrunc>(&TruncMI);
320ba4bcce5SThorsten Schütt   const GBinOp *BinOp = cast<GBinOp>(&BinopMI);
321ba4bcce5SThorsten Schütt 
322ba4bcce5SThorsten Schütt   if (!MRI.hasOneNonDBGUse(BinOp->getReg(0)))
323ba4bcce5SThorsten Schütt     return false;
324ba4bcce5SThorsten Schütt 
325ba4bcce5SThorsten Schütt   Register Dst = Trunc->getReg(0);
326ba4bcce5SThorsten Schütt   LLT DstTy = MRI.getType(Dst);
327ba4bcce5SThorsten Schütt 
328ba4bcce5SThorsten Schütt   // Is narrow binop legal?
329ba4bcce5SThorsten Schütt   if (!isLegalOrBeforeLegalizer({BinOp->getOpcode(), {DstTy}}))
330ba4bcce5SThorsten Schütt     return false;
331ba4bcce5SThorsten Schütt 
332ba4bcce5SThorsten Schütt   MatchInfo = [=](MachineIRBuilder &B) {
333ba4bcce5SThorsten Schütt     auto LHS = B.buildTrunc(DstTy, BinOp->getLHSReg());
334ba4bcce5SThorsten Schütt     auto RHS = B.buildTrunc(DstTy, BinOp->getRHSReg());
335ba4bcce5SThorsten Schütt     B.buildInstr(BinOp->getOpcode(), {Dst}, {LHS, RHS});
336ba4bcce5SThorsten Schütt   };
337ba4bcce5SThorsten Schütt 
338ba4bcce5SThorsten Schütt   return true;
339ba4bcce5SThorsten Schütt }
340ba4bcce5SThorsten Schütt 
341ba4bcce5SThorsten Schütt bool CombinerHelper::matchCastOfInteger(const MachineInstr &CastMI,
342*ee7ca0ddSPaul Bowen-Huggett                                         APInt &MatchInfo) const {
343ba4bcce5SThorsten Schütt   const GExtOrTruncOp *Cast = cast<GExtOrTruncOp>(&CastMI);
344ba4bcce5SThorsten Schütt 
345ba4bcce5SThorsten Schütt   APInt Input = getIConstantFromReg(Cast->getSrcReg(), MRI);
346ba4bcce5SThorsten Schütt 
347ba4bcce5SThorsten Schütt   LLT DstTy = MRI.getType(Cast->getReg(0));
348ba4bcce5SThorsten Schütt 
349ba4bcce5SThorsten Schütt   if (!isConstantLegalOrBeforeLegalizer(DstTy))
350ba4bcce5SThorsten Schütt     return false;
351ba4bcce5SThorsten Schütt 
352ba4bcce5SThorsten Schütt   switch (Cast->getOpcode()) {
353ba4bcce5SThorsten Schütt   case TargetOpcode::G_TRUNC: {
354ba4bcce5SThorsten Schütt     MatchInfo = Input.trunc(DstTy.getScalarSizeInBits());
355ba4bcce5SThorsten Schütt     return true;
356ba4bcce5SThorsten Schütt   }
357ba4bcce5SThorsten Schütt   default:
358ba4bcce5SThorsten Schütt     return false;
359ba4bcce5SThorsten Schütt   }
360ba4bcce5SThorsten Schütt }
361