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 | |
14 | #include "llvm/Analysis/CmpInstAnalysis.h" |
15 | #include "llvm/IR/Constants.h" |
16 | #include "llvm/IR/Instructions.h" |
17 | #include "llvm/IR/PatternMatch.h" |
18 | |
19 | using namespace llvm; |
20 | |
21 | unsigned llvm::getICmpCode(CmpInst::Predicate Pred) { |
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 | |
40 | Constant *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(Ty: CmpInst::makeCmpResultType(opnd_type: OpTy), V: 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(Ty: CmpInst::makeCmpResultType(opnd_type: OpTy), V: 1); |
54 | } |
55 | return nullptr; |
56 | } |
57 | |
58 | bool llvm::predicatesFoldable(ICmpInst::Predicate P1, ICmpInst::Predicate P2) { |
59 | return (CmpInst::isSigned(predicate: P1) == CmpInst::isSigned(predicate: P2)) || |
60 | (CmpInst::isSigned(predicate: P1) && ICmpInst::isEquality(P: P2)) || |
61 | (CmpInst::isSigned(predicate: P2) && ICmpInst::isEquality(P: P1)); |
62 | } |
63 | |
64 | Constant *llvm::getPredForFCmpCode(unsigned Code, Type *OpTy, |
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(Ty: CmpInst::makeCmpResultType(opnd_type: OpTy), V: 0); |
71 | if (Pred == FCmpInst::FCMP_TRUE) |
72 | return ConstantInt::get(Ty: CmpInst::makeCmpResultType(opnd_type: OpTy), V: 1); |
73 | return nullptr; |
74 | } |
75 | |
76 | bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, |
77 | CmpInst::Predicate &Pred, |
78 | Value *&X, APInt &Mask, bool LookThruTrunc) { |
79 | using namespace PatternMatch; |
80 | |
81 | const APInt *C; |
82 | if (!match(V: RHS, P: m_APIntAllowPoison(Res&: C))) |
83 | return false; |
84 | |
85 | switch (Pred) { |
86 | default: |
87 | return false; |
88 | case ICmpInst::ICMP_SLT: |
89 | // X < 0 is equivalent to (X & SignMask) != 0. |
90 | if (!C->isZero()) |
91 | return false; |
92 | Mask = APInt::getSignMask(BitWidth: C->getBitWidth()); |
93 | Pred = ICmpInst::ICMP_NE; |
94 | break; |
95 | case ICmpInst::ICMP_SLE: |
96 | // X <= -1 is equivalent to (X & SignMask) != 0. |
97 | if (!C->isAllOnes()) |
98 | return false; |
99 | Mask = APInt::getSignMask(BitWidth: C->getBitWidth()); |
100 | Pred = ICmpInst::ICMP_NE; |
101 | break; |
102 | case ICmpInst::ICMP_SGT: |
103 | // X > -1 is equivalent to (X & SignMask) == 0. |
104 | if (!C->isAllOnes()) |
105 | return false; |
106 | Mask = APInt::getSignMask(BitWidth: C->getBitWidth()); |
107 | Pred = ICmpInst::ICMP_EQ; |
108 | break; |
109 | case ICmpInst::ICMP_SGE: |
110 | // X >= 0 is equivalent to (X & SignMask) == 0. |
111 | if (!C->isZero()) |
112 | return false; |
113 | Mask = APInt::getSignMask(BitWidth: C->getBitWidth()); |
114 | Pred = ICmpInst::ICMP_EQ; |
115 | break; |
116 | case ICmpInst::ICMP_ULT: |
117 | // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0. |
118 | if (!C->isPowerOf2()) |
119 | return false; |
120 | Mask = -*C; |
121 | Pred = ICmpInst::ICMP_EQ; |
122 | break; |
123 | case ICmpInst::ICMP_ULE: |
124 | // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0. |
125 | if (!(*C + 1).isPowerOf2()) |
126 | return false; |
127 | Mask = ~*C; |
128 | Pred = ICmpInst::ICMP_EQ; |
129 | break; |
130 | case ICmpInst::ICMP_UGT: |
131 | // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0. |
132 | if (!(*C + 1).isPowerOf2()) |
133 | return false; |
134 | Mask = ~*C; |
135 | Pred = ICmpInst::ICMP_NE; |
136 | break; |
137 | case ICmpInst::ICMP_UGE: |
138 | // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0. |
139 | if (!C->isPowerOf2()) |
140 | return false; |
141 | Mask = -*C; |
142 | Pred = ICmpInst::ICMP_NE; |
143 | break; |
144 | } |
145 | |
146 | if (LookThruTrunc && match(V: LHS, P: m_Trunc(Op: m_Value(V&: X)))) { |
147 | Mask = Mask.zext(width: X->getType()->getScalarSizeInBits()); |
148 | } else { |
149 | X = LHS; |
150 | } |
151 | |
152 | return true; |
153 | } |
154 | |