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
27using namespace llvm;
28
29bool 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(Idx: 0);
37 LLT DstTy = MRI.getType(Reg: Dst);
38
39 if (!isConstantLegalOrBeforeLegalizer(Ty: 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(Res: Dst, Val: getICmpTrueVal(TLI: getTargetLowering(),
51 /*IsVector=*/DstTy.isVector(),
52 /*IsFP=*/false));
53 else
54 B.buildConstant(Res: Dst, Val: 0);
55 };
56
57 return true;
58}
59
60bool 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(Idx: 0);
68 LLT DstTy = MRI.getType(Reg: Dst);
69
70 if (!isConstantLegalOrBeforeLegalizer(Ty: 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(Res: Dst, Val: getICmpTrueVal(TLI: getTargetLowering(),
82 /*IsVector=*/DstTy.isVector(),
83 /*IsFP=*/true));
84 else
85 B.buildConstant(Res: Dst, Val: 0);
86 };
87
88 return true;
89}
90
91bool CombinerHelper::matchCanonicalizeICmp(const MachineInstr &MI,
92 BuildFnTy &MatchInfo) const {
93 const GICmp *Cmp = cast<GICmp>(Val: &MI);
94
95 Register Dst = Cmp->getReg(Idx: 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(Const: LHS, MRI)) {
102 if (auto CRHS = GIConstant::getConstant(Const: RHS, MRI))
103 return constantFoldICmp(ICmp: *Cmp, LHSCst: *CLHS, RHSCst: *CRHS, MatchInfo);
104
105 // If we have a constant, make sure it is on the RHS.
106 std::swap(a&: LHS, b&: RHS);
107 Pred = CmpInst::getSwappedPredicate(pred: Pred);
108
109 MatchInfo = [=](MachineIRBuilder &B) { B.buildICmp(Pred, Res: Dst, Op0: LHS, Op1: RHS); };
110 return true;
111 }
112
113 return false;
114}
115
116bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI,
117 BuildFnTy &MatchInfo) const {
118 const GFCmp *Cmp = cast<GFCmp>(Val: &MI);
119
120 Register Dst = Cmp->getReg(Idx: 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(Const: LHS, MRI)) {
128 if (auto CRHS = GFConstant::getConstant(Const: RHS, MRI))
129 return constantFoldFCmp(FCmp: *Cmp, LHSCst: *CLHS, RHSCst: *CRHS, MatchInfo);
130
131 // If we have a constant, make sure it is on the RHS.
132 std::swap(a&: LHS, b&: RHS);
133 Pred = CmpInst::getSwappedPredicate(pred: Pred);
134
135 MatchInfo = [=](MachineIRBuilder &B) {
136 B.buildFCmp(Pred, Res: Dst, Op0: LHS, Op1: RHS, Flags: Cmp->getFlags());
137 };
138 return true;
139 }
140
141 return false;
142}
143