xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/CmpInstAnalysis.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- CmpInstAnalysis.cpp - Utils to help fold compares ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file holds routines to help analyse compare instructions
100b57cec5SDimitry Andric // and fold them into constants or other compare instructions
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Analysis/CmpInstAnalysis.h"
150b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
160b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
170b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace llvm;
200b57cec5SDimitry Andric 
2181ad6265SDimitry Andric unsigned llvm::getICmpCode(CmpInst::Predicate Pred) {
220b57cec5SDimitry Andric   switch (Pred) {
230b57cec5SDimitry Andric       // False -> 0
240b57cec5SDimitry Andric     case ICmpInst::ICMP_UGT: return 1;  // 001
250b57cec5SDimitry Andric     case ICmpInst::ICMP_SGT: return 1;  // 001
260b57cec5SDimitry Andric     case ICmpInst::ICMP_EQ:  return 2;  // 010
270b57cec5SDimitry Andric     case ICmpInst::ICMP_UGE: return 3;  // 011
280b57cec5SDimitry Andric     case ICmpInst::ICMP_SGE: return 3;  // 011
290b57cec5SDimitry Andric     case ICmpInst::ICMP_ULT: return 4;  // 100
300b57cec5SDimitry Andric     case ICmpInst::ICMP_SLT: return 4;  // 100
310b57cec5SDimitry Andric     case ICmpInst::ICMP_NE:  return 5;  // 101
320b57cec5SDimitry Andric     case ICmpInst::ICMP_ULE: return 6;  // 110
330b57cec5SDimitry Andric     case ICmpInst::ICMP_SLE: return 6;  // 110
340b57cec5SDimitry Andric       // True -> 7
350b57cec5SDimitry Andric     default:
360b57cec5SDimitry Andric       llvm_unreachable("Invalid ICmp predicate!");
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric Constant *llvm::getPredForICmpCode(unsigned Code, bool Sign, Type *OpTy,
410b57cec5SDimitry Andric                                    CmpInst::Predicate &Pred) {
420b57cec5SDimitry Andric   switch (Code) {
430b57cec5SDimitry Andric     default: llvm_unreachable("Illegal ICmp code!");
440b57cec5SDimitry Andric     case 0: // False.
450b57cec5SDimitry Andric       return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 0);
460b57cec5SDimitry Andric     case 1: Pred = Sign ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
470b57cec5SDimitry Andric     case 2: Pred = ICmpInst::ICMP_EQ; break;
480b57cec5SDimitry Andric     case 3: Pred = Sign ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
490b57cec5SDimitry Andric     case 4: Pred = Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
500b57cec5SDimitry Andric     case 5: Pred = ICmpInst::ICMP_NE; break;
510b57cec5SDimitry Andric     case 6: Pred = Sign ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
520b57cec5SDimitry Andric     case 7: // True.
530b57cec5SDimitry Andric       return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 1);
540b57cec5SDimitry Andric   }
550b57cec5SDimitry Andric   return nullptr;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric bool llvm::predicatesFoldable(ICmpInst::Predicate P1, ICmpInst::Predicate P2) {
590b57cec5SDimitry Andric   return (CmpInst::isSigned(P1) == CmpInst::isSigned(P2)) ||
600b57cec5SDimitry Andric          (CmpInst::isSigned(P1) && ICmpInst::isEquality(P2)) ||
610b57cec5SDimitry Andric          (CmpInst::isSigned(P2) && ICmpInst::isEquality(P1));
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
6481ad6265SDimitry Andric Constant *llvm::getPredForFCmpCode(unsigned Code, Type *OpTy,
6581ad6265SDimitry Andric                                    CmpInst::Predicate &Pred) {
6681ad6265SDimitry Andric   Pred = static_cast<FCmpInst::Predicate>(Code);
6781ad6265SDimitry Andric   assert(FCmpInst::FCMP_FALSE <= Pred && Pred <= FCmpInst::FCMP_TRUE &&
6881ad6265SDimitry Andric          "Unexpected FCmp predicate!");
6981ad6265SDimitry Andric   if (Pred == FCmpInst::FCMP_FALSE)
7081ad6265SDimitry Andric     return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 0);
7181ad6265SDimitry Andric   if (Pred == FCmpInst::FCMP_TRUE)
7281ad6265SDimitry Andric     return ConstantInt::get(CmpInst::makeCmpResultType(OpTy), 1);
7381ad6265SDimitry Andric   return nullptr;
7481ad6265SDimitry Andric }
7581ad6265SDimitry Andric 
760b57cec5SDimitry Andric bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
770b57cec5SDimitry Andric                                 CmpInst::Predicate &Pred,
780b57cec5SDimitry Andric                                 Value *&X, APInt &Mask, bool LookThruTrunc) {
790b57cec5SDimitry Andric   using namespace PatternMatch;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   const APInt *C;
82*0fca6ea1SDimitry Andric   if (!match(RHS, m_APIntAllowPoison(C)))
830b57cec5SDimitry Andric     return false;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   switch (Pred) {
860b57cec5SDimitry Andric   default:
870b57cec5SDimitry Andric     return false;
880b57cec5SDimitry Andric   case ICmpInst::ICMP_SLT:
890b57cec5SDimitry Andric     // X < 0 is equivalent to (X & SignMask) != 0.
90349cc55cSDimitry Andric     if (!C->isZero())
910b57cec5SDimitry Andric       return false;
920b57cec5SDimitry Andric     Mask = APInt::getSignMask(C->getBitWidth());
930b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
940b57cec5SDimitry Andric     break;
950b57cec5SDimitry Andric   case ICmpInst::ICMP_SLE:
960b57cec5SDimitry Andric     // X <= -1 is equivalent to (X & SignMask) != 0.
97349cc55cSDimitry Andric     if (!C->isAllOnes())
980b57cec5SDimitry Andric       return false;
990b57cec5SDimitry Andric     Mask = APInt::getSignMask(C->getBitWidth());
1000b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
1010b57cec5SDimitry Andric     break;
1020b57cec5SDimitry Andric   case ICmpInst::ICMP_SGT:
1030b57cec5SDimitry Andric     // X > -1 is equivalent to (X & SignMask) == 0.
104349cc55cSDimitry Andric     if (!C->isAllOnes())
1050b57cec5SDimitry Andric       return false;
1060b57cec5SDimitry Andric     Mask = APInt::getSignMask(C->getBitWidth());
1070b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
1080b57cec5SDimitry Andric     break;
1090b57cec5SDimitry Andric   case ICmpInst::ICMP_SGE:
1100b57cec5SDimitry Andric     // X >= 0 is equivalent to (X & SignMask) == 0.
111349cc55cSDimitry Andric     if (!C->isZero())
1120b57cec5SDimitry Andric       return false;
1130b57cec5SDimitry Andric     Mask = APInt::getSignMask(C->getBitWidth());
1140b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
1150b57cec5SDimitry Andric     break;
1160b57cec5SDimitry Andric   case ICmpInst::ICMP_ULT:
1170b57cec5SDimitry Andric     // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
1180b57cec5SDimitry Andric     if (!C->isPowerOf2())
1190b57cec5SDimitry Andric       return false;
1200b57cec5SDimitry Andric     Mask = -*C;
1210b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
1220b57cec5SDimitry Andric     break;
1230b57cec5SDimitry Andric   case ICmpInst::ICMP_ULE:
1240b57cec5SDimitry Andric     // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0.
1250b57cec5SDimitry Andric     if (!(*C + 1).isPowerOf2())
1260b57cec5SDimitry Andric       return false;
1270b57cec5SDimitry Andric     Mask = ~*C;
1280b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
1290b57cec5SDimitry Andric     break;
1300b57cec5SDimitry Andric   case ICmpInst::ICMP_UGT:
1310b57cec5SDimitry Andric     // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
1320b57cec5SDimitry Andric     if (!(*C + 1).isPowerOf2())
1330b57cec5SDimitry Andric       return false;
1340b57cec5SDimitry Andric     Mask = ~*C;
1350b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
1360b57cec5SDimitry Andric     break;
1370b57cec5SDimitry Andric   case ICmpInst::ICMP_UGE:
1380b57cec5SDimitry Andric     // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0.
1390b57cec5SDimitry Andric     if (!C->isPowerOf2())
1400b57cec5SDimitry Andric       return false;
1410b57cec5SDimitry Andric     Mask = -*C;
1420b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
1430b57cec5SDimitry Andric     break;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) {
1470b57cec5SDimitry Andric     Mask = Mask.zext(X->getType()->getScalarSizeInBits());
1480b57cec5SDimitry Andric   } else {
1490b57cec5SDimitry Andric     X = LHS;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   return true;
1530b57cec5SDimitry Andric }
154