1*700637cbSDimitry Andric //===- CombinerHelperCompares.cpp------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This file implements CombinerHelper for G_ICMP.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
13*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
14*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
15*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
16*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17*700637cbSDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
18*700637cbSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
19*700637cbSDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
20*700637cbSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
21*700637cbSDimitry Andric #include "llvm/IR/Instructions.h"
22*700637cbSDimitry Andric #include "llvm/Support/Casting.h"
23*700637cbSDimitry Andric #include <cstdlib>
24*700637cbSDimitry Andric
25*700637cbSDimitry Andric #define DEBUG_TYPE "gi-combiner"
26*700637cbSDimitry Andric
27*700637cbSDimitry Andric using namespace llvm;
28*700637cbSDimitry Andric
constantFoldICmp(const GICmp & ICmp,const GIConstant & LHSCst,const GIConstant & RHSCst,BuildFnTy & MatchInfo) const29*700637cbSDimitry Andric bool CombinerHelper::constantFoldICmp(const GICmp &ICmp,
30*700637cbSDimitry Andric const GIConstant &LHSCst,
31*700637cbSDimitry Andric const GIConstant &RHSCst,
32*700637cbSDimitry Andric BuildFnTy &MatchInfo) const {
33*700637cbSDimitry Andric if (LHSCst.getKind() != GIConstant::GIConstantKind::Scalar)
34*700637cbSDimitry Andric return false;
35*700637cbSDimitry Andric
36*700637cbSDimitry Andric Register Dst = ICmp.getReg(0);
37*700637cbSDimitry Andric LLT DstTy = MRI.getType(Dst);
38*700637cbSDimitry Andric
39*700637cbSDimitry Andric if (!isConstantLegalOrBeforeLegalizer(DstTy))
40*700637cbSDimitry Andric return false;
41*700637cbSDimitry Andric
42*700637cbSDimitry Andric CmpInst::Predicate Pred = ICmp.getCond();
43*700637cbSDimitry Andric APInt LHS = LHSCst.getScalarValue();
44*700637cbSDimitry Andric APInt RHS = RHSCst.getScalarValue();
45*700637cbSDimitry Andric
46*700637cbSDimitry Andric bool Result = ICmpInst::compare(LHS, RHS, Pred);
47*700637cbSDimitry Andric
48*700637cbSDimitry Andric MatchInfo = [=](MachineIRBuilder &B) {
49*700637cbSDimitry Andric if (Result)
50*700637cbSDimitry Andric B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(),
51*700637cbSDimitry Andric /*IsVector=*/DstTy.isVector(),
52*700637cbSDimitry Andric /*IsFP=*/false));
53*700637cbSDimitry Andric else
54*700637cbSDimitry Andric B.buildConstant(Dst, 0);
55*700637cbSDimitry Andric };
56*700637cbSDimitry Andric
57*700637cbSDimitry Andric return true;
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric
constantFoldFCmp(const GFCmp & FCmp,const GFConstant & LHSCst,const GFConstant & RHSCst,BuildFnTy & MatchInfo) const60*700637cbSDimitry Andric bool CombinerHelper::constantFoldFCmp(const GFCmp &FCmp,
61*700637cbSDimitry Andric const GFConstant &LHSCst,
62*700637cbSDimitry Andric const GFConstant &RHSCst,
63*700637cbSDimitry Andric BuildFnTy &MatchInfo) const {
64*700637cbSDimitry Andric if (LHSCst.getKind() != GFConstant::GFConstantKind::Scalar)
65*700637cbSDimitry Andric return false;
66*700637cbSDimitry Andric
67*700637cbSDimitry Andric Register Dst = FCmp.getReg(0);
68*700637cbSDimitry Andric LLT DstTy = MRI.getType(Dst);
69*700637cbSDimitry Andric
70*700637cbSDimitry Andric if (!isConstantLegalOrBeforeLegalizer(DstTy))
71*700637cbSDimitry Andric return false;
72*700637cbSDimitry Andric
73*700637cbSDimitry Andric CmpInst::Predicate Pred = FCmp.getCond();
74*700637cbSDimitry Andric APFloat LHS = LHSCst.getScalarValue();
75*700637cbSDimitry Andric APFloat RHS = RHSCst.getScalarValue();
76*700637cbSDimitry Andric
77*700637cbSDimitry Andric bool Result = FCmpInst::compare(LHS, RHS, Pred);
78*700637cbSDimitry Andric
79*700637cbSDimitry Andric MatchInfo = [=](MachineIRBuilder &B) {
80*700637cbSDimitry Andric if (Result)
81*700637cbSDimitry Andric B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(),
82*700637cbSDimitry Andric /*IsVector=*/DstTy.isVector(),
83*700637cbSDimitry Andric /*IsFP=*/true));
84*700637cbSDimitry Andric else
85*700637cbSDimitry Andric B.buildConstant(Dst, 0);
86*700637cbSDimitry Andric };
87*700637cbSDimitry Andric
88*700637cbSDimitry Andric return true;
89*700637cbSDimitry Andric }
90*700637cbSDimitry Andric
matchCanonicalizeICmp(const MachineInstr & MI,BuildFnTy & MatchInfo) const91*700637cbSDimitry Andric bool CombinerHelper::matchCanonicalizeICmp(const MachineInstr &MI,
92*700637cbSDimitry Andric BuildFnTy &MatchInfo) const {
93*700637cbSDimitry Andric const GICmp *Cmp = cast<GICmp>(&MI);
94*700637cbSDimitry Andric
95*700637cbSDimitry Andric Register Dst = Cmp->getReg(0);
96*700637cbSDimitry Andric Register LHS = Cmp->getLHSReg();
97*700637cbSDimitry Andric Register RHS = Cmp->getRHSReg();
98*700637cbSDimitry Andric
99*700637cbSDimitry Andric CmpInst::Predicate Pred = Cmp->getCond();
100*700637cbSDimitry Andric assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!");
101*700637cbSDimitry Andric if (auto CLHS = GIConstant::getConstant(LHS, MRI)) {
102*700637cbSDimitry Andric if (auto CRHS = GIConstant::getConstant(RHS, MRI))
103*700637cbSDimitry Andric return constantFoldICmp(*Cmp, *CLHS, *CRHS, MatchInfo);
104*700637cbSDimitry Andric
105*700637cbSDimitry Andric // If we have a constant, make sure it is on the RHS.
106*700637cbSDimitry Andric std::swap(LHS, RHS);
107*700637cbSDimitry Andric Pred = CmpInst::getSwappedPredicate(Pred);
108*700637cbSDimitry Andric
109*700637cbSDimitry Andric MatchInfo = [=](MachineIRBuilder &B) { B.buildICmp(Pred, Dst, LHS, RHS); };
110*700637cbSDimitry Andric return true;
111*700637cbSDimitry Andric }
112*700637cbSDimitry Andric
113*700637cbSDimitry Andric return false;
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric
matchCanonicalizeFCmp(const MachineInstr & MI,BuildFnTy & MatchInfo) const116*700637cbSDimitry Andric bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI,
117*700637cbSDimitry Andric BuildFnTy &MatchInfo) const {
118*700637cbSDimitry Andric const GFCmp *Cmp = cast<GFCmp>(&MI);
119*700637cbSDimitry Andric
120*700637cbSDimitry Andric Register Dst = Cmp->getReg(0);
121*700637cbSDimitry Andric Register LHS = Cmp->getLHSReg();
122*700637cbSDimitry Andric Register RHS = Cmp->getRHSReg();
123*700637cbSDimitry Andric
124*700637cbSDimitry Andric CmpInst::Predicate Pred = Cmp->getCond();
125*700637cbSDimitry Andric assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");
126*700637cbSDimitry Andric
127*700637cbSDimitry Andric if (auto CLHS = GFConstant::getConstant(LHS, MRI)) {
128*700637cbSDimitry Andric if (auto CRHS = GFConstant::getConstant(RHS, MRI))
129*700637cbSDimitry Andric return constantFoldFCmp(*Cmp, *CLHS, *CRHS, MatchInfo);
130*700637cbSDimitry Andric
131*700637cbSDimitry Andric // If we have a constant, make sure it is on the RHS.
132*700637cbSDimitry Andric std::swap(LHS, RHS);
133*700637cbSDimitry Andric Pred = CmpInst::getSwappedPredicate(Pred);
134*700637cbSDimitry Andric
135*700637cbSDimitry Andric MatchInfo = [=](MachineIRBuilder &B) {
136*700637cbSDimitry Andric B.buildFCmp(Pred, Dst, LHS, RHS, Cmp->getFlags());
137*700637cbSDimitry Andric };
138*700637cbSDimitry Andric return true;
139*700637cbSDimitry Andric }
140*700637cbSDimitry Andric
141*700637cbSDimitry Andric return false;
142*700637cbSDimitry Andric }
143