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