annotate llvm/lib/Analysis/CmpInstAnalysis.cpp @ 204:e348f3e5c8b2

ReadFromString worked.
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 05 Jun 2021 15:35:13 +0900
parents 1d019706d866
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===- CmpInstAnalysis.cpp - Utils to help fold compares ---------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // This file holds routines to help analyse compare instructions
anatofuz
parents:
diff changeset
10 // and fold them into constants or other compare instructions
anatofuz
parents:
diff changeset
11 //
anatofuz
parents:
diff changeset
12 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 #include "llvm/Analysis/CmpInstAnalysis.h"
anatofuz
parents:
diff changeset
15 #include "llvm/IR/Constants.h"
anatofuz
parents:
diff changeset
16 #include "llvm/IR/Instructions.h"
anatofuz
parents:
diff changeset
17 #include "llvm/IR/PatternMatch.h"
anatofuz
parents:
diff changeset
18
anatofuz
parents:
diff changeset
19 using namespace llvm;
anatofuz
parents:
diff changeset
20
anatofuz
parents:
diff changeset
21 unsigned llvm::getICmpCode(const ICmpInst *ICI, bool InvertPred) {
anatofuz
parents:
diff changeset
22 ICmpInst::Predicate Pred = InvertPred ? ICI->getInversePredicate()
anatofuz
parents:
diff changeset
23 : ICI->getPredicate();
anatofuz
parents:
diff changeset
24 switch (Pred) {
anatofuz
parents:
diff changeset
25 // False -> 0
anatofuz
parents:
diff changeset
26 case ICmpInst::ICMP_UGT: return 1; // 001
anatofuz
parents:
diff changeset
27 case ICmpInst::ICMP_SGT: return 1; // 001
anatofuz
parents:
diff changeset
28 case ICmpInst::ICMP_EQ: return 2; // 010
anatofuz
parents:
diff changeset
29 case ICmpInst::ICMP_UGE: return 3; // 011
anatofuz
parents:
diff changeset
30 case ICmpInst::ICMP_SGE: return 3; // 011
anatofuz
parents:
diff changeset
31 case ICmpInst::ICMP_ULT: return 4; // 100
anatofuz
parents:
diff changeset
32 case ICmpInst::ICMP_SLT: return 4; // 100
anatofuz
parents:
diff changeset
33 case ICmpInst::ICMP_NE: return 5; // 101
anatofuz
parents:
diff changeset
34 case ICmpInst::ICMP_ULE: return 6; // 110
anatofuz
parents:
diff changeset
35 case ICmpInst::ICMP_SLE: return 6; // 110
anatofuz
parents:
diff changeset
36 // True -> 7
anatofuz
parents:
diff changeset
37 default:
anatofuz
parents:
diff changeset
38 llvm_unreachable("Invalid ICmp predicate!");
anatofuz
parents:
diff changeset
39 }
anatofuz
parents:
diff changeset
40 }
anatofuz
parents:
diff changeset
41
anatofuz
parents:
diff changeset
42 Constant *llvm::getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy,
anatofuz
parents:
diff changeset
43 CmpInst::Predicate &Pred) {
anatofuz
parents:
diff changeset
44 switch (Code) {
anatofuz
parents:
diff changeset
45 default: llvm_unreachable("Illegal ICmp code!");
anatofuz
parents:
diff changeset
46 case 0: // False.
anatofuz
parents:
diff changeset
47 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 0);
anatofuz
parents:
diff changeset
48 case 1: Pred = Sign ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
anatofuz
parents:
diff changeset
49 case 2: Pred = ICmpInst::ICMP_EQ; break;
anatofuz
parents:
diff changeset
50 case 3: Pred = Sign ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
anatofuz
parents:
diff changeset
51 case 4: Pred = Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
anatofuz
parents:
diff changeset
52 case 5: Pred = ICmpInst::ICMP_NE; break;
anatofuz
parents:
diff changeset
53 case 6: Pred = Sign ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
anatofuz
parents:
diff changeset
54 case 7: // True.
anatofuz
parents:
diff changeset
55 return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 1);
anatofuz
parents:
diff changeset
56 }
anatofuz
parents:
diff changeset
57 return nullptr;
anatofuz
parents:
diff changeset
58 }
anatofuz
parents:
diff changeset
59
anatofuz
parents:
diff changeset
60 bool llvm::predicatesFoldable(ICmpInst::Predicate P1, ICmpInst::Predicate P2) {
anatofuz
parents:
diff changeset
61 return (CmpInst::isSigned(P1) == CmpInst::isSigned(P2)) ||
anatofuz
parents:
diff changeset
62 (CmpInst::isSigned(P1) && ICmpInst::isEquality(P2)) ||
anatofuz
parents:
diff changeset
63 (CmpInst::isSigned(P2) && ICmpInst::isEquality(P1));
anatofuz
parents:
diff changeset
64 }
anatofuz
parents:
diff changeset
65
anatofuz
parents:
diff changeset
66 bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
anatofuz
parents:
diff changeset
67 CmpInst::Predicate &Pred,
anatofuz
parents:
diff changeset
68 Value *&X, APInt &Mask, bool LookThruTrunc) {
anatofuz
parents:
diff changeset
69 using namespace PatternMatch;
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 const APInt *C;
anatofuz
parents:
diff changeset
72 if (!match(RHS, m_APInt(C)))
anatofuz
parents:
diff changeset
73 return false;
anatofuz
parents:
diff changeset
74
anatofuz
parents:
diff changeset
75 switch (Pred) {
anatofuz
parents:
diff changeset
76 default:
anatofuz
parents:
diff changeset
77 return false;
anatofuz
parents:
diff changeset
78 case ICmpInst::ICMP_SLT:
anatofuz
parents:
diff changeset
79 // X < 0 is equivalent to (X & SignMask) != 0.
anatofuz
parents:
diff changeset
80 if (!C->isNullValue())
anatofuz
parents:
diff changeset
81 return false;
anatofuz
parents:
diff changeset
82 Mask = APInt::getSignMask(C->getBitWidth());
anatofuz
parents:
diff changeset
83 Pred = ICmpInst::ICMP_NE;
anatofuz
parents:
diff changeset
84 break;
anatofuz
parents:
diff changeset
85 case ICmpInst::ICMP_SLE:
anatofuz
parents:
diff changeset
86 // X <= -1 is equivalent to (X & SignMask) != 0.
anatofuz
parents:
diff changeset
87 if (!C->isAllOnesValue())
anatofuz
parents:
diff changeset
88 return false;
anatofuz
parents:
diff changeset
89 Mask = APInt::getSignMask(C->getBitWidth());
anatofuz
parents:
diff changeset
90 Pred = ICmpInst::ICMP_NE;
anatofuz
parents:
diff changeset
91 break;
anatofuz
parents:
diff changeset
92 case ICmpInst::ICMP_SGT:
anatofuz
parents:
diff changeset
93 // X > -1 is equivalent to (X & SignMask) == 0.
anatofuz
parents:
diff changeset
94 if (!C->isAllOnesValue())
anatofuz
parents:
diff changeset
95 return false;
anatofuz
parents:
diff changeset
96 Mask = APInt::getSignMask(C->getBitWidth());
anatofuz
parents:
diff changeset
97 Pred = ICmpInst::ICMP_EQ;
anatofuz
parents:
diff changeset
98 break;
anatofuz
parents:
diff changeset
99 case ICmpInst::ICMP_SGE:
anatofuz
parents:
diff changeset
100 // X >= 0 is equivalent to (X & SignMask) == 0.
anatofuz
parents:
diff changeset
101 if (!C->isNullValue())
anatofuz
parents:
diff changeset
102 return false;
anatofuz
parents:
diff changeset
103 Mask = APInt::getSignMask(C->getBitWidth());
anatofuz
parents:
diff changeset
104 Pred = ICmpInst::ICMP_EQ;
anatofuz
parents:
diff changeset
105 break;
anatofuz
parents:
diff changeset
106 case ICmpInst::ICMP_ULT:
anatofuz
parents:
diff changeset
107 // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
anatofuz
parents:
diff changeset
108 if (!C->isPowerOf2())
anatofuz
parents:
diff changeset
109 return false;
anatofuz
parents:
diff changeset
110 Mask = -*C;
anatofuz
parents:
diff changeset
111 Pred = ICmpInst::ICMP_EQ;
anatofuz
parents:
diff changeset
112 break;
anatofuz
parents:
diff changeset
113 case ICmpInst::ICMP_ULE:
anatofuz
parents:
diff changeset
114 // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0.
anatofuz
parents:
diff changeset
115 if (!(*C + 1).isPowerOf2())
anatofuz
parents:
diff changeset
116 return false;
anatofuz
parents:
diff changeset
117 Mask = ~*C;
anatofuz
parents:
diff changeset
118 Pred = ICmpInst::ICMP_EQ;
anatofuz
parents:
diff changeset
119 break;
anatofuz
parents:
diff changeset
120 case ICmpInst::ICMP_UGT:
anatofuz
parents:
diff changeset
121 // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
anatofuz
parents:
diff changeset
122 if (!(*C + 1).isPowerOf2())
anatofuz
parents:
diff changeset
123 return false;
anatofuz
parents:
diff changeset
124 Mask = ~*C;
anatofuz
parents:
diff changeset
125 Pred = ICmpInst::ICMP_NE;
anatofuz
parents:
diff changeset
126 break;
anatofuz
parents:
diff changeset
127 case ICmpInst::ICMP_UGE:
anatofuz
parents:
diff changeset
128 // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0.
anatofuz
parents:
diff changeset
129 if (!C->isPowerOf2())
anatofuz
parents:
diff changeset
130 return false;
anatofuz
parents:
diff changeset
131 Mask = -*C;
anatofuz
parents:
diff changeset
132 Pred = ICmpInst::ICMP_NE;
anatofuz
parents:
diff changeset
133 break;
anatofuz
parents:
diff changeset
134 }
anatofuz
parents:
diff changeset
135
anatofuz
parents:
diff changeset
136 if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) {
anatofuz
parents:
diff changeset
137 Mask = Mask.zext(X->getType()->getScalarSizeInBits());
anatofuz
parents:
diff changeset
138 } else {
anatofuz
parents:
diff changeset
139 X = LHS;
anatofuz
parents:
diff changeset
140 }
anatofuz
parents:
diff changeset
141
anatofuz
parents:
diff changeset
142 return true;
anatofuz
parents:
diff changeset
143 }