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(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 | |
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(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 | |
91 | bool 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 | |
116 | bool 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 | |