LLVM 20.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
59 return (CmpInst::isSigned(P1) == CmpInst::isSigned(P2)) ||
62}
63
65 CmpInst::Predicate &Pred) {
66 Pred = static_cast<FCmpInst::Predicate>(Code);
67 assert(FCmpInst::FCMP_FALSE <= Pred && Pred <= FCmpInst::FCMP_TRUE &&
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 LookThruTrunc, bool AllowNonZeroC) {
79 using namespace PatternMatch;
80
81 const APInt *OrigC;
82 if (!ICmpInst::isRelational(Pred) || !match(RHS, m_APIntAllowPoison(OrigC)))
83 return std::nullopt;
84
85 bool Inverted = false;
86 if (ICmpInst::isGT(Pred) || ICmpInst::isGE(Pred)) {
87 Inverted = true;
88 Pred = ICmpInst::getInversePredicate(Pred);
89 }
90
91 APInt C = *OrigC;
92 if (ICmpInst::isLE(Pred)) {
93 if (ICmpInst::isSigned(Pred) ? C.isMaxSignedValue() : C.isMaxValue())
94 return std::nullopt;
95 ++C;
96 Pred = ICmpInst::getStrictPredicate(Pred);
97 }
98
99 DecomposedBitTest Result;
100 switch (Pred) {
101 default:
102 llvm_unreachable("Unexpected predicate");
103 case ICmpInst::ICMP_SLT: {
104 // X < 0 is equivalent to (X & SignMask) != 0.
105 if (C.isZero()) {
106 Result.Mask = APInt::getSignMask(C.getBitWidth());
107 Result.C = APInt::getZero(C.getBitWidth());
108 Result.Pred = ICmpInst::ICMP_NE;
109 break;
110 }
111
112 APInt FlippedSign = C ^ APInt::getSignMask(C.getBitWidth());
113 if (FlippedSign.isPowerOf2()) {
114 // X s< 10000100 is equivalent to (X & 11111100 == 10000000)
115 Result.Mask = -FlippedSign;
116 Result.C = APInt::getSignMask(C.getBitWidth());
117 Result.Pred = ICmpInst::ICMP_EQ;
118 break;
119 }
120
121 if (FlippedSign.isNegatedPowerOf2()) {
122 // X s< 01111100 is equivalent to (X & 11111100 != 01111100)
123 Result.Mask = FlippedSign;
124 Result.C = C;
125 Result.Pred = ICmpInst::ICMP_NE;
126 break;
127 }
128
129 return std::nullopt;
130 }
131 case ICmpInst::ICMP_ULT:
132 // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
133 if (C.isPowerOf2()) {
134 Result.Mask = -C;
135 Result.C = APInt::getZero(C.getBitWidth());
136 Result.Pred = ICmpInst::ICMP_EQ;
137 break;
138 }
139
140 // X u< 11111100 is equivalent to (X & 11111100 != 11111100)
141 if (C.isNegatedPowerOf2()) {
142 Result.Mask = C;
143 Result.C = C;
144 Result.Pred = ICmpInst::ICMP_NE;
145 break;
146 }
147
148 return std::nullopt;
149 }
150
151 if (!AllowNonZeroC && !Result.C.isZero())
152 return std::nullopt;
153
154 if (Inverted)
155 Result.Pred = ICmpInst::getInversePredicate(Result.Pred);
156
157 Value *X;
158 if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) {
159 Result.X = X;
160 Result.Mask = Result.Mask.zext(X->getType()->getScalarSizeInBits());
161 Result.C = Result.C.zext(X->getType()->getScalarSizeInBits());
162 } else {
163 Result.X = LHS;
164 }
165
166 return Result;
167}
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
bool isNegatedPowerOf2() const
Check if this APInt's negated value is a power of two greater than zero.
Definition: APInt.h:449
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
Definition: APInt.h:229
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition: APInt.h:440
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition: APInt.h:200
static Type * makeCmpResultType(Type *opnd_type)
Create a result type for fcmp/icmp.
Definition: InstrTypes.h:988
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:673
bool isSigned() const
Definition: InstrTypes.h:928
This is an important base class in LLVM.
Definition: Constant.h:42
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.
bool isRelational() const
Return true if the predicate is relational (not 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:74
#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
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:49
apint_match m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
Definition: PatternMatch.h:305
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
Definition: PatternMatch.h:92
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Constant * getPredForFCmpCode(unsigned Code, Type *OpTy, CmpInst::Predicate &Pred)
This is the complement of getFCmpCode.
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...
std::optional< DecomposedBitTest > decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred, bool LookThroughTrunc=true, bool AllowNonZeroC=false)
Decompose an icmp into the form ((X & Mask) pred C) if possible.
unsigned getICmpCode(CmpInst::Predicate Pred)
Encode a icmp predicate into a three bit mask.
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.