LLVM 23.0.0git
CmpInstAnalysis.cpp
Go to the documentation of this file.
1//===- CmpInstAnalysis.cpp - Utils to help fold compares ---------------===//
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 holds routines to help analyse compare instructions
10// and fold them into constants or other compare instructions
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/IR/Constants.h"
18
19using namespace llvm;
20
22 switch (Pred) {
23 // False -> 0
24 case ICmpInst::ICMP_UGT: return 1; // 001
25 case ICmpInst::ICMP_SGT: return 1; // 001
26 case ICmpInst::ICMP_EQ: return 2; // 010
27 case ICmpInst::ICMP_UGE: return 3; // 011
28 case ICmpInst::ICMP_SGE: return 3; // 011
29 case ICmpInst::ICMP_ULT: return 4; // 100
30 case ICmpInst::ICMP_SLT: return 4; // 100
31 case ICmpInst::ICMP_NE: return 5; // 101
32 case ICmpInst::ICMP_ULE: return 6; // 110
33 case ICmpInst::ICMP_SLE: return 6; // 110
34 // True -> 7
35 default:
36 llvm_unreachable("Invalid ICmp predicate!");
37 }
38}
39
40Constant *llvm::getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy,
41 CmpInst::Predicate &Pred) {
42 switch (Code) {
43 default: llvm_unreachable("Illegal ICmp code!");
44 case 0: // False.
45 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 0);
46 case 1: Pred = Sign ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
47 case 2: Pred = ICmpInst::ICMP_EQ; break;
48 case 3: Pred = Sign ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
49 case 4: Pred = Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
50 case 5: Pred = ICmpInst::ICMP_NE; break;
51 case 6: Pred = Sign ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
52 case 7: // True.
53 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 1);
54 }
55 return nullptr;
56}
57
63
65 CmpInst::Predicate &Pred) {
66 Pred = static_cast<FCmpInst::Predicate>(Code);
68 "Unexpected FCmp predicate!");
69 if (Pred == FCmpInst::FCMP_FALSE)
70 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 0);
71 if (Pred == FCmpInst::FCMP_TRUE)
72 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 1);
73 return nullptr;
74}
75
76std::optional<DecomposedBitTest>
78 bool LookThroughTrunc, bool AllowNonZeroC,
79 bool DecomposeAnd) {
80 using namespace PatternMatch;
81
82 const APInt *OrigC;
83 if ((ICmpInst::isEquality(Pred) && !DecomposeAnd) ||
84 !match(RHS, m_APIntAllowPoison(OrigC)))
85 return std::nullopt;
86
87 bool Inverted = false;
88 if (ICmpInst::isGT(Pred) || ICmpInst::isGE(Pred)) {
89 Inverted = true;
91 }
92
93 APInt C = *OrigC;
94 if (ICmpInst::isLE(Pred)) {
95 if (ICmpInst::isSigned(Pred) ? C.isMaxSignedValue() : C.isMaxValue())
96 return std::nullopt;
97 ++C;
99 }
100
101 DecomposedBitTest Result;
102 switch (Pred) {
103 default:
104 llvm_unreachable("Unexpected predicate");
105 case ICmpInst::ICMP_SLT: {
106 // X < 0 is equivalent to (X & SignMask) != 0.
107 if (C.isZero()) {
108 Result.Mask = APInt::getSignMask(C.getBitWidth());
109 Result.C = APInt::getZero(C.getBitWidth());
110 Result.Pred = ICmpInst::ICMP_NE;
111 break;
112 }
113
114 APInt FlippedSign = C ^ APInt::getSignMask(C.getBitWidth());
115 if (FlippedSign.isPowerOf2()) {
116 // X s< 10000100 is equivalent to (X & 11111100 == 10000000)
117 Result.Mask = -FlippedSign;
118 Result.C = APInt::getSignMask(C.getBitWidth());
119 Result.Pred = ICmpInst::ICMP_EQ;
120 break;
121 }
122
123 if (FlippedSign.isNegatedPowerOf2()) {
124 // X s< 01111100 is equivalent to (X & 11111100 != 01111100)
125 Result.Mask = FlippedSign;
126 Result.C = C;
127 Result.Pred = ICmpInst::ICMP_NE;
128 break;
129 }
130
131 return std::nullopt;
132 }
133 case ICmpInst::ICMP_ULT: {
134 // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
135 if (C.isPowerOf2()) {
136 Result.Mask = -C;
137 Result.C = APInt::getZero(C.getBitWidth());
138 Result.Pred = ICmpInst::ICMP_EQ;
139 break;
140 }
141
142 // X u< 11111100 is equivalent to (X & 11111100 != 11111100)
143 if (C.isNegatedPowerOf2()) {
144 Result.Mask = C;
145 Result.C = C;
146 Result.Pred = ICmpInst::ICMP_NE;
147 break;
148 }
149
150 return std::nullopt;
151 }
153 case ICmpInst::ICMP_NE: {
154 assert(DecomposeAnd);
155 const APInt *AndC;
156 Value *AndVal;
157 if (match(LHS, m_And(m_Value(AndVal), m_APIntAllowPoison(AndC)))) {
158 LHS = AndVal;
159 Result.Mask = *AndC;
160 Result.C = C;
161 Result.Pred = Pred;
162 break;
163 }
164
165 // Try to convert (trunc X) eq/ne C into (X & Mask) eq/ne C
166 if (LookThroughTrunc && isa<TruncInst>(LHS)) {
167 Result.Pred = Pred;
168 Result.Mask = APInt::getAllOnes(C.getBitWidth());
169 Result.C = C;
170 break;
171 }
172
173 return std::nullopt;
174 }
175 }
176
177 if (!AllowNonZeroC && !Result.C.isZero())
178 return std::nullopt;
179
180 if (Inverted)
181 Result.Pred = ICmpInst::getInversePredicate(Result.Pred);
182
183 Value *X;
184 if (LookThroughTrunc && match(LHS, m_Trunc(m_Value(X)))) {
185 Result.X = X;
186 Result.Mask = Result.Mask.zext(X->getType()->getScalarSizeInBits());
187 Result.C = Result.C.zext(X->getType()->getScalarSizeInBits());
188 } else {
189 Result.X = LHS;
190 }
191
192 return Result;
193}
194
195std::optional<DecomposedBitTest> llvm::decomposeBitTest(Value *Cond,
196 bool LookThroughTrunc,
197 bool AllowNonZeroC,
198 bool DecomposeAnd) {
199 using namespace PatternMatch;
200 if (auto *ICmp = dyn_cast<ICmpInst>(Cond)) {
201 // Don't allow pointers. Splat vectors are fine.
202 if (!ICmp->getOperand(0)->getType()->isIntOrIntVectorTy())
203 return std::nullopt;
204 return decomposeBitTestICmp(ICmp->getOperand(0), ICmp->getOperand(1),
205 ICmp->getPredicate(), LookThroughTrunc,
206 AllowNonZeroC, DecomposeAnd);
207 }
208 Value *X;
209 if (Cond->getType()->isIntOrIntVectorTy(1) &&
210 (match(Cond, m_Trunc(m_Value(X))) ||
212 DecomposedBitTest Result;
213 Result.X = X;
214 unsigned BitWidth = X->getType()->getScalarSizeInBits();
215 Result.Mask = APInt(BitWidth, 1);
216 Result.C = APInt::getZero(BitWidth);
218
219 return Result;
220 }
221
222 return std::nullopt;
223}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const SmallVectorImpl< MachineOperand > & Cond
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:235
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
Definition APInt.h:450
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
Definition APInt.h:230
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:441
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Definition InstrTypes.h:982
Predicate getStrictPredicate() const
For example, SGE -> SGT, SLE -> SLT, ULE -> ULT, UGE -> UGT.
Definition InstrTypes.h:858
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:693
@ ICMP_SLT
signed less than
Definition InstrTypes.h:705
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:706
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:700
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:699
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:703
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:701
@ ICMP_NE
not equal
Definition InstrTypes.h:698
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:704
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:702
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:678
bool isSigned() const
Definition InstrTypes.h:930
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:789
This is an important base class in LLVM.
Definition Constant.h:43
static bool isGE(Predicate P)
Return true if the predicate is SGE or UGE.
static bool isGT(Predicate P)
Return true if the predicate is SGT or UGT.
bool isEquality() const
Return true if this predicate is either EQ or NE.
static bool isEquality(Predicate P)
Return true if this predicate is either EQ or NE.
static bool isLE(Predicate P)
Return true if the predicate is SLE or ULE.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM Value Representation.
Definition Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
bool match(Val *V, const Pattern &P)
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
Constant * getPredForFCmpCode(unsigned Code, Type *OpTy, CmpInst::Predicate &Pred)
This is the complement of getFCmpCode.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool predicatesFoldable(CmpInst::Predicate P1, CmpInst::Predicate P2)
Return true if both predicates match sign or if at least one of them is an equality comparison (which...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
std::optional< DecomposedBitTest > decomposeBitTest(Value *Cond, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
constexpr unsigned BitWidth
unsigned getICmpCode(CmpInst::Predicate Pred)
Encode a icmp predicate into a three bit mask.
std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false, bool DecomposeAnd=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
Constant * getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy, CmpInst::Predicate &Pred)
This is the complement of getICmpCode.
Represents the operation icmp (X & Mask) pred C, where pred can only be eq or ne.