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
24#define DEBUG_TYPE "gi-combiner"
25
26using namespace llvm;
27
28bool CombinerHelper::constantFoldICmp(const GICmp &ICmp,
29 const GIConstant &LHSCst,
30 const GIConstant &RHSCst,
31 BuildFnTy &MatchInfo) const {
32 if (LHSCst.getKind() != GIConstant::GIConstantKind::Scalar)
33 return false;
34
35 Register Dst = ICmp.getReg(Idx: 0);
36 LLT DstTy = MRI.getType(Reg: Dst);
37
38 if (!isConstantLegalOrBeforeLegalizer(Ty: DstTy))
39 return false;
40
41 CmpInst::Predicate Pred = ICmp.getCond();
42 APInt LHS = LHSCst.getScalarValue();
43 APInt RHS = RHSCst.getScalarValue();
44
45 bool Result = ICmpInst::compare(LHS, RHS, Pred);
46
47 MatchInfo = [=](MachineIRBuilder &B) {
48 if (Result)
49 B.buildConstant(Res: Dst, Val: getICmpTrueVal(TLI: getTargetLowering(),
50 /*IsVector=*/DstTy.isVector(),
51 /*IsFP=*/false));
52 else
53 B.buildConstant(Res: Dst, Val: 0);
54 };
55
56 return true;
57}
58
59bool CombinerHelper::constantFoldFCmp(const GFCmp &FCmp,
60 const GFConstant &LHSCst,
61 const GFConstant &RHSCst,
62 BuildFnTy &MatchInfo) const {
63 if (LHSCst.getKind() != GFConstant::GFConstantKind::Scalar)
64 return false;
65
66 Register Dst = FCmp.getReg(Idx: 0);
67 LLT DstTy = MRI.getType(Reg: Dst);
68
69 if (!isConstantLegalOrBeforeLegalizer(Ty: DstTy))
70 return false;
71
72 CmpInst::Predicate Pred = FCmp.getCond();
73 APFloat LHS = LHSCst.getScalarValue();
74 APFloat RHS = RHSCst.getScalarValue();
75
76 bool Result = FCmpInst::compare(LHS, RHS, Pred);
77
78 MatchInfo = [=](MachineIRBuilder &B) {
79 if (Result)
80 B.buildConstant(Res: Dst, Val: getICmpTrueVal(TLI: getTargetLowering(),
81 /*IsVector=*/DstTy.isVector(),
82 /*IsFP=*/true));
83 else
84 B.buildConstant(Res: Dst, Val: 0);
85 };
86
87 return true;
88}
89
90bool CombinerHelper::matchCanonicalizeICmp(const MachineInstr &MI,
91 BuildFnTy &MatchInfo) const {
92 const GICmp *Cmp = cast<GICmp>(Val: &MI);
93
94 Register Dst = Cmp->getReg(Idx: 0);
95 Register LHS = Cmp->getLHSReg();
96 Register RHS = Cmp->getRHSReg();
97
98 CmpInst::Predicate Pred = Cmp->getCond();
99 assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!");
100 if (auto CLHS = GIConstant::getConstant(Const: LHS, MRI)) {
101 if (auto CRHS = GIConstant::getConstant(Const: RHS, MRI))
102 return constantFoldICmp(ICmp: *Cmp, LHSCst: *CLHS, RHSCst: *CRHS, MatchInfo);
103
104 // If we have a constant, make sure it is on the RHS.
105 std::swap(a&: LHS, b&: RHS);
106 Pred = CmpInst::getSwappedPredicate(pred: Pred);
107
108 MatchInfo = [=](MachineIRBuilder &B) { B.buildICmp(Pred, Res: Dst, Op0: LHS, Op1: RHS); };
109 return true;
110 }
111
112 return false;
113}
114
115bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI,
116 BuildFnTy &MatchInfo) const {
117 const GFCmp *Cmp = cast<GFCmp>(Val: &MI);
118
119 Register Dst = Cmp->getReg(Idx: 0);
120 Register LHS = Cmp->getLHSReg();
121 Register RHS = Cmp->getRHSReg();
122
123 CmpInst::Predicate Pred = Cmp->getCond();
124 assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!");
125
126 if (auto CLHS = GFConstant::getConstant(Const: LHS, MRI)) {
127 if (auto CRHS = GFConstant::getConstant(Const: RHS, MRI))
128 return constantFoldFCmp(FCmp: *Cmp, LHSCst: *CLHS, RHSCst: *CRHS, MatchInfo);
129
130 // If we have a constant, make sure it is on the RHS.
131 std::swap(a&: LHS, b&: RHS);
132 Pred = CmpInst::getSwappedPredicate(pred: Pred);
133
134 MatchInfo = [=](MachineIRBuilder &B) {
135 B.buildFCmp(Pred, Res: Dst, Op0: LHS, Op1: RHS, Flags: Cmp->getFlags());
136 };
137 return true;
138 }
139
140 return false;
141}
142