xref: /llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp (revision db8c84fc7a75dd60bcfff7160b51e1a55e7e0f73)
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,
292ca300f9SThorsten Schütt                                       BuildFnTy &MatchInfo) {
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,
622ca300f9SThorsten Schütt                                       BuildFnTy &MatchInfo) {
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,
972ca300f9SThorsten Schütt                                      BuildFnTy &MatchInfo) {
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,
119bfcfb0fdSThorsten Schütt                                         BuildFnTy &MatchInfo) {
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 }
164*db8c84fcSThorsten Schütt 
165*db8c84fcSThorsten Schütt bool CombinerHelper::isCastFree(unsigned Opcode, LLT ToTy, LLT FromTy) const {
166*db8c84fcSThorsten Schütt   const TargetLowering &TLI = getTargetLowering();
167*db8c84fcSThorsten Schütt   const DataLayout &DL = getDataLayout();
168*db8c84fcSThorsten Schütt   LLVMContext &Ctx = getContext();
169*db8c84fcSThorsten Schütt 
170*db8c84fcSThorsten Schütt   switch (Opcode) {
171*db8c84fcSThorsten Schütt   case TargetOpcode::G_ANYEXT:
172*db8c84fcSThorsten Schütt   case TargetOpcode::G_ZEXT:
173*db8c84fcSThorsten Schütt     return TLI.isZExtFree(FromTy, ToTy, DL, Ctx);
174*db8c84fcSThorsten Schütt   case TargetOpcode::G_TRUNC:
175*db8c84fcSThorsten Schütt     return TLI.isTruncateFree(FromTy, ToTy, DL, Ctx);
176*db8c84fcSThorsten Schütt   default:
177*db8c84fcSThorsten Schütt     return false;
178*db8c84fcSThorsten Schütt   }
179*db8c84fcSThorsten Schütt }
180*db8c84fcSThorsten Schütt 
181*db8c84fcSThorsten Schütt bool CombinerHelper::matchCastOfSelect(const MachineInstr &CastMI,
182*db8c84fcSThorsten Schütt                                        const MachineInstr &SelectMI,
183*db8c84fcSThorsten Schütt                                        BuildFnTy &MatchInfo) {
184*db8c84fcSThorsten Schütt   const GExtOrTruncOp *Cast = cast<GExtOrTruncOp>(&CastMI);
185*db8c84fcSThorsten Schütt   const GSelect *Select = cast<GSelect>(&SelectMI);
186*db8c84fcSThorsten Schütt 
187*db8c84fcSThorsten Schütt   if (!MRI.hasOneNonDBGUse(Select->getReg(0)))
188*db8c84fcSThorsten Schütt     return false;
189*db8c84fcSThorsten Schütt 
190*db8c84fcSThorsten Schütt   Register Dst = Cast->getReg(0);
191*db8c84fcSThorsten Schütt   LLT DstTy = MRI.getType(Dst);
192*db8c84fcSThorsten Schütt   LLT CondTy = MRI.getType(Select->getCondReg());
193*db8c84fcSThorsten Schütt   Register TrueReg = Select->getTrueReg();
194*db8c84fcSThorsten Schütt   Register FalseReg = Select->getFalseReg();
195*db8c84fcSThorsten Schütt   LLT SrcTy = MRI.getType(TrueReg);
196*db8c84fcSThorsten Schütt   Register Cond = Select->getCondReg();
197*db8c84fcSThorsten Schütt 
198*db8c84fcSThorsten Schütt   if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SELECT, {DstTy, CondTy}}))
199*db8c84fcSThorsten Schütt     return false;
200*db8c84fcSThorsten Schütt 
201*db8c84fcSThorsten Schütt   if (!isCastFree(Cast->getOpcode(), DstTy, SrcTy))
202*db8c84fcSThorsten Schütt     return false;
203*db8c84fcSThorsten Schütt 
204*db8c84fcSThorsten Schütt   MatchInfo = [=](MachineIRBuilder &B) {
205*db8c84fcSThorsten Schütt     auto True = B.buildInstr(Cast->getOpcode(), {DstTy}, {TrueReg});
206*db8c84fcSThorsten Schütt     auto False = B.buildInstr(Cast->getOpcode(), {DstTy}, {FalseReg});
207*db8c84fcSThorsten Schütt     B.buildSelect(Dst, Cond, True, False);
208*db8c84fcSThorsten Schütt   };
209*db8c84fcSThorsten Schütt 
210*db8c84fcSThorsten Schütt   return true;
211*db8c84fcSThorsten Schütt }
212