10b57cec5SDimitry Andric //===- InstCombineCasts.cpp -----------------------------------------------===// 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 implements the visit functions for cast operations. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "InstCombineInternal.h" 140b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 150b57cec5SDimitry Andric #include "llvm/Analysis/ConstantFolding.h" 16e8d8bef9SDimitry Andric #include "llvm/IR/DataLayout.h" 17bdd1243dSDimitry Andric #include "llvm/IR/DebugInfo.h" 180b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h" 190b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 20e8d8bef9SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombiner.h" 21bdd1243dSDimitry Andric #include <optional> 22bdd1243dSDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric using namespace PatternMatch; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #define DEBUG_TYPE "instcombine" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric /// Given an expression that CanEvaluateTruncated or CanEvaluateSExtd returns 290b57cec5SDimitry Andric /// true for, actually insert the code to evaluate the expression. 30e8d8bef9SDimitry Andric Value *InstCombinerImpl::EvaluateInDifferentType(Value *V, Type *Ty, 310b57cec5SDimitry Andric bool isSigned) { 325f757f3fSDimitry Andric if (Constant *C = dyn_cast<Constant>(V)) 335f757f3fSDimitry Andric return ConstantFoldIntegerCast(C, Ty, isSigned, DL); 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // Otherwise, it must be an instruction. 360b57cec5SDimitry Andric Instruction *I = cast<Instruction>(V); 370b57cec5SDimitry Andric Instruction *Res = nullptr; 380b57cec5SDimitry Andric unsigned Opc = I->getOpcode(); 390b57cec5SDimitry Andric switch (Opc) { 400b57cec5SDimitry Andric case Instruction::Add: 410b57cec5SDimitry Andric case Instruction::Sub: 420b57cec5SDimitry Andric case Instruction::Mul: 430b57cec5SDimitry Andric case Instruction::And: 440b57cec5SDimitry Andric case Instruction::Or: 450b57cec5SDimitry Andric case Instruction::Xor: 460b57cec5SDimitry Andric case Instruction::AShr: 470b57cec5SDimitry Andric case Instruction::LShr: 480b57cec5SDimitry Andric case Instruction::Shl: 490b57cec5SDimitry Andric case Instruction::UDiv: 500b57cec5SDimitry Andric case Instruction::URem: { 510b57cec5SDimitry Andric Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); 520b57cec5SDimitry Andric Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); 530b57cec5SDimitry Andric Res = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); 540b57cec5SDimitry Andric break; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric case Instruction::Trunc: 570b57cec5SDimitry Andric case Instruction::ZExt: 580b57cec5SDimitry Andric case Instruction::SExt: 590b57cec5SDimitry Andric // If the source type of the cast is the type we're trying for then we can 600b57cec5SDimitry Andric // just return the source. There's no need to insert it because it is not 610b57cec5SDimitry Andric // new. 620b57cec5SDimitry Andric if (I->getOperand(0)->getType() == Ty) 630b57cec5SDimitry Andric return I->getOperand(0); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Otherwise, must be the same type of cast, so just reinsert a new one. 660b57cec5SDimitry Andric // This also handles the case of zext(trunc(x)) -> zext(x). 670b57cec5SDimitry Andric Res = CastInst::CreateIntegerCast(I->getOperand(0), Ty, 680b57cec5SDimitry Andric Opc == Instruction::SExt); 690b57cec5SDimitry Andric break; 700b57cec5SDimitry Andric case Instruction::Select: { 710b57cec5SDimitry Andric Value *True = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); 720b57cec5SDimitry Andric Value *False = EvaluateInDifferentType(I->getOperand(2), Ty, isSigned); 730b57cec5SDimitry Andric Res = SelectInst::Create(I->getOperand(0), True, False); 740b57cec5SDimitry Andric break; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric case Instruction::PHI: { 770b57cec5SDimitry Andric PHINode *OPN = cast<PHINode>(I); 780b57cec5SDimitry Andric PHINode *NPN = PHINode::Create(Ty, OPN->getNumIncomingValues()); 790b57cec5SDimitry Andric for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { 800b57cec5SDimitry Andric Value *V = 810b57cec5SDimitry Andric EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, isSigned); 820b57cec5SDimitry Andric NPN->addIncoming(V, OPN->getIncomingBlock(i)); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric Res = NPN; 850b57cec5SDimitry Andric break; 860b57cec5SDimitry Andric } 87bdd1243dSDimitry Andric case Instruction::FPToUI: 88bdd1243dSDimitry Andric case Instruction::FPToSI: 89bdd1243dSDimitry Andric Res = CastInst::Create( 90bdd1243dSDimitry Andric static_cast<Instruction::CastOps>(Opc), I->getOperand(0), Ty); 91bdd1243dSDimitry Andric break; 9206c3fb27SDimitry Andric case Instruction::Call: 9306c3fb27SDimitry Andric if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { 9406c3fb27SDimitry Andric switch (II->getIntrinsicID()) { 9506c3fb27SDimitry Andric default: 9606c3fb27SDimitry Andric llvm_unreachable("Unsupported call!"); 9706c3fb27SDimitry Andric case Intrinsic::vscale: { 9806c3fb27SDimitry Andric Function *Fn = 9906c3fb27SDimitry Andric Intrinsic::getDeclaration(I->getModule(), Intrinsic::vscale, {Ty}); 10006c3fb27SDimitry Andric Res = CallInst::Create(Fn->getFunctionType(), Fn); 10106c3fb27SDimitry Andric break; 10206c3fb27SDimitry Andric } 10306c3fb27SDimitry Andric } 10406c3fb27SDimitry Andric } 10506c3fb27SDimitry Andric break; 1067a6dacacSDimitry Andric case Instruction::ShuffleVector: { 1077a6dacacSDimitry Andric auto *ScalarTy = cast<VectorType>(Ty)->getElementType(); 1087a6dacacSDimitry Andric auto *VTy = cast<VectorType>(I->getOperand(0)->getType()); 1097a6dacacSDimitry Andric auto *FixedTy = VectorType::get(ScalarTy, VTy->getElementCount()); 1107a6dacacSDimitry Andric Value *Op0 = EvaluateInDifferentType(I->getOperand(0), FixedTy, isSigned); 1117a6dacacSDimitry Andric Value *Op1 = EvaluateInDifferentType(I->getOperand(1), FixedTy, isSigned); 1127a6dacacSDimitry Andric Res = new ShuffleVectorInst(Op0, Op1, 1137a6dacacSDimitry Andric cast<ShuffleVectorInst>(I)->getShuffleMask()); 1147a6dacacSDimitry Andric break; 1157a6dacacSDimitry Andric } 1160b57cec5SDimitry Andric default: 1170b57cec5SDimitry Andric // TODO: Can handle more cases here. 1180b57cec5SDimitry Andric llvm_unreachable("Unreachable!"); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric Res->takeName(I); 1225f757f3fSDimitry Andric return InsertNewInstWith(Res, I->getIterator()); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 125e8d8bef9SDimitry Andric Instruction::CastOps 126e8d8bef9SDimitry Andric InstCombinerImpl::isEliminableCastPair(const CastInst *CI1, 1270b57cec5SDimitry Andric const CastInst *CI2) { 1280b57cec5SDimitry Andric Type *SrcTy = CI1->getSrcTy(); 1290b57cec5SDimitry Andric Type *MidTy = CI1->getDestTy(); 1300b57cec5SDimitry Andric Type *DstTy = CI2->getDestTy(); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric Instruction::CastOps firstOp = CI1->getOpcode(); 1330b57cec5SDimitry Andric Instruction::CastOps secondOp = CI2->getOpcode(); 1340b57cec5SDimitry Andric Type *SrcIntPtrTy = 1350b57cec5SDimitry Andric SrcTy->isPtrOrPtrVectorTy() ? DL.getIntPtrType(SrcTy) : nullptr; 1360b57cec5SDimitry Andric Type *MidIntPtrTy = 1370b57cec5SDimitry Andric MidTy->isPtrOrPtrVectorTy() ? DL.getIntPtrType(MidTy) : nullptr; 1380b57cec5SDimitry Andric Type *DstIntPtrTy = 1390b57cec5SDimitry Andric DstTy->isPtrOrPtrVectorTy() ? DL.getIntPtrType(DstTy) : nullptr; 1400b57cec5SDimitry Andric unsigned Res = CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, 1410b57cec5SDimitry Andric DstTy, SrcIntPtrTy, MidIntPtrTy, 1420b57cec5SDimitry Andric DstIntPtrTy); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // We don't want to form an inttoptr or ptrtoint that converts to an integer 1450b57cec5SDimitry Andric // type that differs from the pointer size. 1460b57cec5SDimitry Andric if ((Res == Instruction::IntToPtr && SrcTy != DstIntPtrTy) || 1470b57cec5SDimitry Andric (Res == Instruction::PtrToInt && DstTy != SrcIntPtrTy)) 1480b57cec5SDimitry Andric Res = 0; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric return Instruction::CastOps(Res); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// Implement the transforms common to all CastInst visitors. 154e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::commonCastTransforms(CastInst &CI) { 1550b57cec5SDimitry Andric Value *Src = CI.getOperand(0); 156fe6060f1SDimitry Andric Type *Ty = CI.getType(); 1570b57cec5SDimitry Andric 15806c3fb27SDimitry Andric if (auto *SrcC = dyn_cast<Constant>(Src)) 15906c3fb27SDimitry Andric if (Constant *Res = ConstantFoldCastOperand(CI.getOpcode(), SrcC, Ty, DL)) 16006c3fb27SDimitry Andric return replaceInstUsesWith(CI, Res); 16106c3fb27SDimitry Andric 1620b57cec5SDimitry Andric // Try to eliminate a cast of a cast. 1630b57cec5SDimitry Andric if (auto *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast 1640b57cec5SDimitry Andric if (Instruction::CastOps NewOpc = isEliminableCastPair(CSrc, &CI)) { 1650b57cec5SDimitry Andric // The first cast (CSrc) is eliminable so we need to fix up or replace 1660b57cec5SDimitry Andric // the second cast (CI). CSrc will then have a good chance of being dead. 1670b57cec5SDimitry Andric auto *Res = CastInst::Create(NewOpc, CSrc->getOperand(0), Ty); 1680b57cec5SDimitry Andric // Point debug users of the dying cast to the new one. 1690b57cec5SDimitry Andric if (CSrc->hasOneUse()) 1700b57cec5SDimitry Andric replaceAllDbgUsesWith(*CSrc, *Res, CI, DT); 1710b57cec5SDimitry Andric return Res; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric if (auto *Sel = dyn_cast<SelectInst>(Src)) { 1765ffd83dbSDimitry Andric // We are casting a select. Try to fold the cast into the select if the 1775ffd83dbSDimitry Andric // select does not have a compare instruction with matching operand types 1785ffd83dbSDimitry Andric // or the select is likely better done in a narrow type. 1795ffd83dbSDimitry Andric // Creating a select with operands that are different sizes than its 1800b57cec5SDimitry Andric // condition may inhibit other folds and lead to worse codegen. 1810b57cec5SDimitry Andric auto *Cmp = dyn_cast<CmpInst>(Sel->getCondition()); 1825ffd83dbSDimitry Andric if (!Cmp || Cmp->getOperand(0)->getType() != Sel->getType() || 1835ffd83dbSDimitry Andric (CI.getOpcode() == Instruction::Trunc && 1845ffd83dbSDimitry Andric shouldChangeType(CI.getSrcTy(), CI.getType()))) { 185*0fca6ea1SDimitry Andric 186*0fca6ea1SDimitry Andric // If it's a bitcast involving vectors, make sure it has the same number 187*0fca6ea1SDimitry Andric // of elements on both sides. 188*0fca6ea1SDimitry Andric if (CI.getOpcode() != Instruction::BitCast || 189*0fca6ea1SDimitry Andric match(&CI, m_ElementWiseBitCast(m_Value()))) { 1900b57cec5SDimitry Andric if (Instruction *NV = FoldOpIntoSelect(CI, Sel)) { 1910b57cec5SDimitry Andric replaceAllDbgUsesWith(*Sel, *NV, CI, DT); 1920b57cec5SDimitry Andric return NV; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1955ffd83dbSDimitry Andric } 196*0fca6ea1SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric // If we are casting a PHI, then fold the cast into the PHI. 1990b57cec5SDimitry Andric if (auto *PN = dyn_cast<PHINode>(Src)) { 2000b57cec5SDimitry Andric // Don't do this if it would create a PHI node with an illegal type from a 2010b57cec5SDimitry Andric // legal type. 2020b57cec5SDimitry Andric if (!Src->getType()->isIntegerTy() || !CI.getType()->isIntegerTy() || 2035ffd83dbSDimitry Andric shouldChangeType(CI.getSrcTy(), CI.getType())) 2040b57cec5SDimitry Andric if (Instruction *NV = foldOpIntoPhi(CI, PN)) 2050b57cec5SDimitry Andric return NV; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 208fe6060f1SDimitry Andric // Canonicalize a unary shuffle after the cast if neither operation changes 209fe6060f1SDimitry Andric // the size or element size of the input vector. 210fe6060f1SDimitry Andric // TODO: We could allow size-changing ops if that doesn't harm codegen. 211fe6060f1SDimitry Andric // cast (shuffle X, Mask) --> shuffle (cast X), Mask 212fe6060f1SDimitry Andric Value *X; 213fe6060f1SDimitry Andric ArrayRef<int> Mask; 214fe6060f1SDimitry Andric if (match(Src, m_OneUse(m_Shuffle(m_Value(X), m_Undef(), m_Mask(Mask))))) { 215fe6060f1SDimitry Andric // TODO: Allow scalable vectors? 216fe6060f1SDimitry Andric auto *SrcTy = dyn_cast<FixedVectorType>(X->getType()); 217fe6060f1SDimitry Andric auto *DestTy = dyn_cast<FixedVectorType>(Ty); 218fe6060f1SDimitry Andric if (SrcTy && DestTy && 219fe6060f1SDimitry Andric SrcTy->getNumElements() == DestTy->getNumElements() && 220fe6060f1SDimitry Andric SrcTy->getPrimitiveSizeInBits() == DestTy->getPrimitiveSizeInBits()) { 221fe6060f1SDimitry Andric Value *CastX = Builder.CreateCast(CI.getOpcode(), X, DestTy); 222349cc55cSDimitry Andric return new ShuffleVectorInst(CastX, Mask); 223fe6060f1SDimitry Andric } 224fe6060f1SDimitry Andric } 225fe6060f1SDimitry Andric 2260b57cec5SDimitry Andric return nullptr; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric /// Constants and extensions/truncates from the destination type are always 2300b57cec5SDimitry Andric /// free to be evaluated in that type. This is a helper for canEvaluate*. 2310b57cec5SDimitry Andric static bool canAlwaysEvaluateInType(Value *V, Type *Ty) { 2320b57cec5SDimitry Andric if (isa<Constant>(V)) 2335f757f3fSDimitry Andric return match(V, m_ImmConstant()); 2345f757f3fSDimitry Andric 2350b57cec5SDimitry Andric Value *X; 2360b57cec5SDimitry Andric if ((match(V, m_ZExtOrSExt(m_Value(X))) || match(V, m_Trunc(m_Value(X)))) && 2370b57cec5SDimitry Andric X->getType() == Ty) 2380b57cec5SDimitry Andric return true; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric return false; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric /// Filter out values that we can not evaluate in the destination type for free. 2440b57cec5SDimitry Andric /// This is a helper for canEvaluate*. 2450b57cec5SDimitry Andric static bool canNotEvaluateInType(Value *V, Type *Ty) { 2460b57cec5SDimitry Andric if (!isa<Instruction>(V)) 2470b57cec5SDimitry Andric return true; 2480b57cec5SDimitry Andric // We don't extend or shrink something that has multiple uses -- doing so 2490b57cec5SDimitry Andric // would require duplicating the instruction which isn't profitable. 2500b57cec5SDimitry Andric if (!V->hasOneUse()) 2510b57cec5SDimitry Andric return true; 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric return false; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric /// Return true if we can evaluate the specified expression tree as type Ty 2570b57cec5SDimitry Andric /// instead of its larger type, and arrive with the same value. 2580b57cec5SDimitry Andric /// This is used by code that tries to eliminate truncates. 2590b57cec5SDimitry Andric /// 2600b57cec5SDimitry Andric /// Ty will always be a type smaller than V. We should return true if trunc(V) 2610b57cec5SDimitry Andric /// can be computed by computing V in the smaller type. If V is an instruction, 2620b57cec5SDimitry Andric /// then trunc(inst(x,y)) can be computed as inst(trunc(x),trunc(y)), which only 2630b57cec5SDimitry Andric /// makes sense if x and y can be efficiently truncated. 2640b57cec5SDimitry Andric /// 2650b57cec5SDimitry Andric /// This function works on both vectors and scalars. 2660b57cec5SDimitry Andric /// 267e8d8bef9SDimitry Andric static bool canEvaluateTruncated(Value *V, Type *Ty, InstCombinerImpl &IC, 2680b57cec5SDimitry Andric Instruction *CxtI) { 2690b57cec5SDimitry Andric if (canAlwaysEvaluateInType(V, Ty)) 2700b57cec5SDimitry Andric return true; 2710b57cec5SDimitry Andric if (canNotEvaluateInType(V, Ty)) 2720b57cec5SDimitry Andric return false; 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric auto *I = cast<Instruction>(V); 2750b57cec5SDimitry Andric Type *OrigTy = V->getType(); 2760b57cec5SDimitry Andric switch (I->getOpcode()) { 2770b57cec5SDimitry Andric case Instruction::Add: 2780b57cec5SDimitry Andric case Instruction::Sub: 2790b57cec5SDimitry Andric case Instruction::Mul: 2800b57cec5SDimitry Andric case Instruction::And: 2810b57cec5SDimitry Andric case Instruction::Or: 2820b57cec5SDimitry Andric case Instruction::Xor: 2830b57cec5SDimitry Andric // These operators can all arbitrarily be extended or truncated. 2840b57cec5SDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI) && 2850b57cec5SDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, CxtI); 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric case Instruction::UDiv: 2880b57cec5SDimitry Andric case Instruction::URem: { 2890b57cec5SDimitry Andric // UDiv and URem can be truncated if all the truncated bits are zero. 2900b57cec5SDimitry Andric uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); 2910b57cec5SDimitry Andric uint32_t BitWidth = Ty->getScalarSizeInBits(); 2920b57cec5SDimitry Andric assert(BitWidth < OrigBitWidth && "Unexpected bitwidths!"); 2930b57cec5SDimitry Andric APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); 294*0fca6ea1SDimitry Andric // Do not preserve the original context instruction. Simplifying div/rem 295*0fca6ea1SDimitry Andric // based on later context may introduce a trap. 296*0fca6ea1SDimitry Andric if (IC.MaskedValueIsZero(I->getOperand(0), Mask, 0, I) && 297*0fca6ea1SDimitry Andric IC.MaskedValueIsZero(I->getOperand(1), Mask, 0, I)) { 298*0fca6ea1SDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, I) && 299*0fca6ea1SDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, I); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric break; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric case Instruction::Shl: { 3045ffd83dbSDimitry Andric // If we are truncating the result of this SHL, and if it's a shift of an 3055ffd83dbSDimitry Andric // inrange amount, we can always perform a SHL in a smaller type. 3060b57cec5SDimitry Andric uint32_t BitWidth = Ty->getScalarSizeInBits(); 3075ffd83dbSDimitry Andric KnownBits AmtKnownBits = 3085ffd83dbSDimitry Andric llvm::computeKnownBits(I->getOperand(1), IC.getDataLayout()); 3095ffd83dbSDimitry Andric if (AmtKnownBits.getMaxValue().ult(BitWidth)) 3105ffd83dbSDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI) && 3115ffd83dbSDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, CxtI); 3120b57cec5SDimitry Andric break; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric case Instruction::LShr: { 3150b57cec5SDimitry Andric // If this is a truncate of a logical shr, we can truncate it to a smaller 3160b57cec5SDimitry Andric // lshr iff we know that the bits we would otherwise be shifting in are 3170b57cec5SDimitry Andric // already zeros. 3185ffd83dbSDimitry Andric // TODO: It is enough to check that the bits we would be shifting in are 3195ffd83dbSDimitry Andric // zero - use AmtKnownBits.getMaxValue(). 3200b57cec5SDimitry Andric uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); 3210b57cec5SDimitry Andric uint32_t BitWidth = Ty->getScalarSizeInBits(); 3225ffd83dbSDimitry Andric KnownBits AmtKnownBits = 3235ffd83dbSDimitry Andric llvm::computeKnownBits(I->getOperand(1), IC.getDataLayout()); 3245ffd83dbSDimitry Andric APInt ShiftedBits = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); 3255ffd83dbSDimitry Andric if (AmtKnownBits.getMaxValue().ult(BitWidth) && 3265ffd83dbSDimitry Andric IC.MaskedValueIsZero(I->getOperand(0), ShiftedBits, 0, CxtI)) { 3275ffd83dbSDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI) && 3285ffd83dbSDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, CxtI); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric break; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric case Instruction::AShr: { 3330b57cec5SDimitry Andric // If this is a truncate of an arithmetic shr, we can truncate it to a 3340b57cec5SDimitry Andric // smaller ashr iff we know that all the bits from the sign bit of the 3350b57cec5SDimitry Andric // original type and the sign bit of the truncate type are similar. 3360b57cec5SDimitry Andric // TODO: It is enough to check that the bits we would be shifting in are 3370b57cec5SDimitry Andric // similar to sign bit of the truncate type. 3380b57cec5SDimitry Andric uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); 3390b57cec5SDimitry Andric uint32_t BitWidth = Ty->getScalarSizeInBits(); 3405ffd83dbSDimitry Andric KnownBits AmtKnownBits = 3415ffd83dbSDimitry Andric llvm::computeKnownBits(I->getOperand(1), IC.getDataLayout()); 3425ffd83dbSDimitry Andric unsigned ShiftedBits = OrigBitWidth - BitWidth; 3435ffd83dbSDimitry Andric if (AmtKnownBits.getMaxValue().ult(BitWidth) && 3445ffd83dbSDimitry Andric ShiftedBits < IC.ComputeNumSignBits(I->getOperand(0), 0, CxtI)) 3455ffd83dbSDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI) && 3465ffd83dbSDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, CxtI); 3470b57cec5SDimitry Andric break; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric case Instruction::Trunc: 3500b57cec5SDimitry Andric // trunc(trunc(x)) -> trunc(x) 3510b57cec5SDimitry Andric return true; 3520b57cec5SDimitry Andric case Instruction::ZExt: 3530b57cec5SDimitry Andric case Instruction::SExt: 3540b57cec5SDimitry Andric // trunc(ext(x)) -> ext(x) if the source type is smaller than the new dest 3550b57cec5SDimitry Andric // trunc(ext(x)) -> trunc(x) if the source type is larger than the new dest 3560b57cec5SDimitry Andric return true; 3570b57cec5SDimitry Andric case Instruction::Select: { 3580b57cec5SDimitry Andric SelectInst *SI = cast<SelectInst>(I); 3590b57cec5SDimitry Andric return canEvaluateTruncated(SI->getTrueValue(), Ty, IC, CxtI) && 3600b57cec5SDimitry Andric canEvaluateTruncated(SI->getFalseValue(), Ty, IC, CxtI); 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric case Instruction::PHI: { 3630b57cec5SDimitry Andric // We can change a phi if we can change all operands. Note that we never 3640b57cec5SDimitry Andric // get into trouble with cyclic PHIs here because we only consider 3650b57cec5SDimitry Andric // instructions with a single use. 3660b57cec5SDimitry Andric PHINode *PN = cast<PHINode>(I); 3670b57cec5SDimitry Andric for (Value *IncValue : PN->incoming_values()) 3680b57cec5SDimitry Andric if (!canEvaluateTruncated(IncValue, Ty, IC, CxtI)) 3690b57cec5SDimitry Andric return false; 3700b57cec5SDimitry Andric return true; 3710b57cec5SDimitry Andric } 372bdd1243dSDimitry Andric case Instruction::FPToUI: 373bdd1243dSDimitry Andric case Instruction::FPToSI: { 374bdd1243dSDimitry Andric // If the integer type can hold the max FP value, it is safe to cast 375bdd1243dSDimitry Andric // directly to that type. Otherwise, we may create poison via overflow 376bdd1243dSDimitry Andric // that did not exist in the original code. 377bdd1243dSDimitry Andric Type *InputTy = I->getOperand(0)->getType()->getScalarType(); 378bdd1243dSDimitry Andric const fltSemantics &Semantics = InputTy->getFltSemantics(); 37906c3fb27SDimitry Andric uint32_t MinBitWidth = 38006c3fb27SDimitry Andric APFloatBase::semanticsIntSizeInBits(Semantics, 38106c3fb27SDimitry Andric I->getOpcode() == Instruction::FPToSI); 38206c3fb27SDimitry Andric return Ty->getScalarSizeInBits() >= MinBitWidth; 383bdd1243dSDimitry Andric } 3847a6dacacSDimitry Andric case Instruction::ShuffleVector: 3857a6dacacSDimitry Andric return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI) && 3867a6dacacSDimitry Andric canEvaluateTruncated(I->getOperand(1), Ty, IC, CxtI); 3870b57cec5SDimitry Andric default: 3880b57cec5SDimitry Andric // TODO: Can handle more cases here. 3890b57cec5SDimitry Andric break; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric return false; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric /// Given a vector that is bitcast to an integer, optionally logically 3960b57cec5SDimitry Andric /// right-shifted, and truncated, convert it to an extractelement. 3970b57cec5SDimitry Andric /// Example (big endian): 3980b57cec5SDimitry Andric /// trunc (lshr (bitcast <4 x i32> %X to i128), 32) to i32 3990b57cec5SDimitry Andric /// ---> 4000b57cec5SDimitry Andric /// extractelement <4 x i32> %X, 1 401e8d8bef9SDimitry Andric static Instruction *foldVecTruncToExtElt(TruncInst &Trunc, 402e8d8bef9SDimitry Andric InstCombinerImpl &IC) { 4030b57cec5SDimitry Andric Value *TruncOp = Trunc.getOperand(0); 4040b57cec5SDimitry Andric Type *DestType = Trunc.getType(); 4050b57cec5SDimitry Andric if (!TruncOp->hasOneUse() || !isa<IntegerType>(DestType)) 4060b57cec5SDimitry Andric return nullptr; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric Value *VecInput = nullptr; 4090b57cec5SDimitry Andric ConstantInt *ShiftVal = nullptr; 4100b57cec5SDimitry Andric if (!match(TruncOp, m_CombineOr(m_BitCast(m_Value(VecInput)), 4110b57cec5SDimitry Andric m_LShr(m_BitCast(m_Value(VecInput)), 4120b57cec5SDimitry Andric m_ConstantInt(ShiftVal)))) || 4130b57cec5SDimitry Andric !isa<VectorType>(VecInput->getType())) 4140b57cec5SDimitry Andric return nullptr; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric VectorType *VecType = cast<VectorType>(VecInput->getType()); 4170b57cec5SDimitry Andric unsigned VecWidth = VecType->getPrimitiveSizeInBits(); 4180b57cec5SDimitry Andric unsigned DestWidth = DestType->getPrimitiveSizeInBits(); 4190b57cec5SDimitry Andric unsigned ShiftAmount = ShiftVal ? ShiftVal->getZExtValue() : 0; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric if ((VecWidth % DestWidth != 0) || (ShiftAmount % DestWidth != 0)) 4220b57cec5SDimitry Andric return nullptr; 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric // If the element type of the vector doesn't match the result type, 4250b57cec5SDimitry Andric // bitcast it to a vector type that we can extract from. 4260b57cec5SDimitry Andric unsigned NumVecElts = VecWidth / DestWidth; 4270b57cec5SDimitry Andric if (VecType->getElementType() != DestType) { 4285ffd83dbSDimitry Andric VecType = FixedVectorType::get(DestType, NumVecElts); 4290b57cec5SDimitry Andric VecInput = IC.Builder.CreateBitCast(VecInput, VecType, "bc"); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric unsigned Elt = ShiftAmount / DestWidth; 4330b57cec5SDimitry Andric if (IC.getDataLayout().isBigEndian()) 4340b57cec5SDimitry Andric Elt = NumVecElts - 1 - Elt; 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric return ExtractElementInst::Create(VecInput, IC.Builder.getInt32(Elt)); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 439e8d8bef9SDimitry Andric /// Funnel/Rotate left/right may occur in a wider type than necessary because of 440e8d8bef9SDimitry Andric /// type promotion rules. Try to narrow the inputs and convert to funnel shift. 441e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::narrowFunnelShift(TruncInst &Trunc) { 4420b57cec5SDimitry Andric assert((isa<VectorType>(Trunc.getSrcTy()) || 4430b57cec5SDimitry Andric shouldChangeType(Trunc.getSrcTy(), Trunc.getType())) && 4440b57cec5SDimitry Andric "Don't narrow to an illegal scalar type"); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric // Bail out on strange types. It is possible to handle some of these patterns 4470b57cec5SDimitry Andric // even with non-power-of-2 sizes, but it is not a likely scenario. 4480b57cec5SDimitry Andric Type *DestTy = Trunc.getType(); 4490b57cec5SDimitry Andric unsigned NarrowWidth = DestTy->getScalarSizeInBits(); 450fe6060f1SDimitry Andric unsigned WideWidth = Trunc.getSrcTy()->getScalarSizeInBits(); 4510b57cec5SDimitry Andric if (!isPowerOf2_32(NarrowWidth)) 4520b57cec5SDimitry Andric return nullptr; 4530b57cec5SDimitry Andric 454e8d8bef9SDimitry Andric // First, find an or'd pair of opposite shifts: 455e8d8bef9SDimitry Andric // trunc (or (lshr ShVal0, ShAmt0), (shl ShVal1, ShAmt1)) 456e8d8bef9SDimitry Andric BinaryOperator *Or0, *Or1; 457e8d8bef9SDimitry Andric if (!match(Trunc.getOperand(0), m_OneUse(m_Or(m_BinOp(Or0), m_BinOp(Or1))))) 4580b57cec5SDimitry Andric return nullptr; 4590b57cec5SDimitry Andric 460e8d8bef9SDimitry Andric Value *ShVal0, *ShVal1, *ShAmt0, *ShAmt1; 461e8d8bef9SDimitry Andric if (!match(Or0, m_OneUse(m_LogicalShift(m_Value(ShVal0), m_Value(ShAmt0)))) || 462e8d8bef9SDimitry Andric !match(Or1, m_OneUse(m_LogicalShift(m_Value(ShVal1), m_Value(ShAmt1)))) || 463e8d8bef9SDimitry Andric Or0->getOpcode() == Or1->getOpcode()) 4640b57cec5SDimitry Andric return nullptr; 4650b57cec5SDimitry Andric 466e8d8bef9SDimitry Andric // Canonicalize to or(shl(ShVal0, ShAmt0), lshr(ShVal1, ShAmt1)). 467e8d8bef9SDimitry Andric if (Or0->getOpcode() == BinaryOperator::LShr) { 468e8d8bef9SDimitry Andric std::swap(Or0, Or1); 469e8d8bef9SDimitry Andric std::swap(ShVal0, ShVal1); 470e8d8bef9SDimitry Andric std::swap(ShAmt0, ShAmt1); 471e8d8bef9SDimitry Andric } 472e8d8bef9SDimitry Andric assert(Or0->getOpcode() == BinaryOperator::Shl && 473e8d8bef9SDimitry Andric Or1->getOpcode() == BinaryOperator::LShr && 474e8d8bef9SDimitry Andric "Illegal or(shift,shift) pair"); 4750b57cec5SDimitry Andric 476e8d8bef9SDimitry Andric // Match the shift amount operands for a funnel/rotate pattern. This always 477e8d8bef9SDimitry Andric // matches a subtraction on the R operand. 478e8d8bef9SDimitry Andric auto matchShiftAmount = [&](Value *L, Value *R, unsigned Width) -> Value * { 4790b57cec5SDimitry Andric // The shift amounts may add up to the narrow bit width: 480e8d8bef9SDimitry Andric // (shl ShVal0, L) | (lshr ShVal1, Width - L) 481fe6060f1SDimitry Andric // If this is a funnel shift (different operands are shifted), then the 482fe6060f1SDimitry Andric // shift amount can not over-shift (create poison) in the narrow type. 483fe6060f1SDimitry Andric unsigned MaxShiftAmountWidth = Log2_32(NarrowWidth); 484fe6060f1SDimitry Andric APInt HiBitMask = ~APInt::getLowBitsSet(WideWidth, MaxShiftAmountWidth); 485fe6060f1SDimitry Andric if (ShVal0 == ShVal1 || MaskedValueIsZero(L, HiBitMask)) 4860b57cec5SDimitry Andric if (match(R, m_OneUse(m_Sub(m_SpecificInt(Width), m_Specific(L))))) 4870b57cec5SDimitry Andric return L; 4880b57cec5SDimitry Andric 489e8d8bef9SDimitry Andric // The following patterns currently only work for rotation patterns. 490e8d8bef9SDimitry Andric // TODO: Add more general funnel-shift compatible patterns. 491e8d8bef9SDimitry Andric if (ShVal0 != ShVal1) 492e8d8bef9SDimitry Andric return nullptr; 493e8d8bef9SDimitry Andric 4940b57cec5SDimitry Andric // The shift amount may be masked with negation: 495e8d8bef9SDimitry Andric // (shl ShVal0, (X & (Width - 1))) | (lshr ShVal1, ((-X) & (Width - 1))) 4960b57cec5SDimitry Andric Value *X; 4970b57cec5SDimitry Andric unsigned Mask = Width - 1; 4980b57cec5SDimitry Andric if (match(L, m_And(m_Value(X), m_SpecificInt(Mask))) && 4990b57cec5SDimitry Andric match(R, m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask)))) 5000b57cec5SDimitry Andric return X; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric // Same as above, but the shift amount may be extended after masking: 5030b57cec5SDimitry Andric if (match(L, m_ZExt(m_And(m_Value(X), m_SpecificInt(Mask)))) && 5040b57cec5SDimitry Andric match(R, m_ZExt(m_And(m_Neg(m_Specific(X)), m_SpecificInt(Mask))))) 5050b57cec5SDimitry Andric return X; 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric return nullptr; 5080b57cec5SDimitry Andric }; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric Value *ShAmt = matchShiftAmount(ShAmt0, ShAmt1, NarrowWidth); 511e8d8bef9SDimitry Andric bool IsFshl = true; // Sub on LSHR. 5120b57cec5SDimitry Andric if (!ShAmt) { 5130b57cec5SDimitry Andric ShAmt = matchShiftAmount(ShAmt1, ShAmt0, NarrowWidth); 514e8d8bef9SDimitry Andric IsFshl = false; // Sub on SHL. 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric if (!ShAmt) 5170b57cec5SDimitry Andric return nullptr; 5180b57cec5SDimitry Andric 519fe6060f1SDimitry Andric // The right-shifted value must have high zeros in the wide type (for example 520fe6060f1SDimitry Andric // from 'zext', 'and' or 'shift'). High bits of the left-shifted value are 521fe6060f1SDimitry Andric // truncated, so those do not matter. 5220b57cec5SDimitry Andric APInt HiBitMask = APInt::getHighBitsSet(WideWidth, WideWidth - NarrowWidth); 523fe6060f1SDimitry Andric if (!MaskedValueIsZero(ShVal1, HiBitMask, 0, &Trunc)) 5240b57cec5SDimitry Andric return nullptr; 5250b57cec5SDimitry Andric 5265f757f3fSDimitry Andric // Adjust the width of ShAmt for narrowed funnel shift operation: 5275f757f3fSDimitry Andric // - Zero-extend if ShAmt is narrower than the destination type. 5285f757f3fSDimitry Andric // - Truncate if ShAmt is wider, discarding non-significant high-order bits. 5295f757f3fSDimitry Andric // This prepares ShAmt for llvm.fshl.i8(trunc(ShVal), trunc(ShVal), 5305f757f3fSDimitry Andric // zext/trunc(ShAmt)). 5315f757f3fSDimitry Andric Value *NarrowShAmt = Builder.CreateZExtOrTrunc(ShAmt, DestTy); 5325f757f3fSDimitry Andric 533e8d8bef9SDimitry Andric Value *X, *Y; 534e8d8bef9SDimitry Andric X = Y = Builder.CreateTrunc(ShVal0, DestTy); 535e8d8bef9SDimitry Andric if (ShVal0 != ShVal1) 536e8d8bef9SDimitry Andric Y = Builder.CreateTrunc(ShVal1, DestTy); 5370b57cec5SDimitry Andric Intrinsic::ID IID = IsFshl ? Intrinsic::fshl : Intrinsic::fshr; 5380b57cec5SDimitry Andric Function *F = Intrinsic::getDeclaration(Trunc.getModule(), IID, DestTy); 539fe6060f1SDimitry Andric return CallInst::Create(F, {X, Y, NarrowShAmt}); 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric /// Try to narrow the width of math or bitwise logic instructions by pulling a 5430b57cec5SDimitry Andric /// truncate ahead of binary operators. 544e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::narrowBinOp(TruncInst &Trunc) { 5450b57cec5SDimitry Andric Type *SrcTy = Trunc.getSrcTy(); 5460b57cec5SDimitry Andric Type *DestTy = Trunc.getType(); 54781ad6265SDimitry Andric unsigned SrcWidth = SrcTy->getScalarSizeInBits(); 54881ad6265SDimitry Andric unsigned DestWidth = DestTy->getScalarSizeInBits(); 54981ad6265SDimitry Andric 5500b57cec5SDimitry Andric if (!isa<VectorType>(SrcTy) && !shouldChangeType(SrcTy, DestTy)) 5510b57cec5SDimitry Andric return nullptr; 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric BinaryOperator *BinOp; 5540b57cec5SDimitry Andric if (!match(Trunc.getOperand(0), m_OneUse(m_BinOp(BinOp)))) 5550b57cec5SDimitry Andric return nullptr; 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric Value *BinOp0 = BinOp->getOperand(0); 5580b57cec5SDimitry Andric Value *BinOp1 = BinOp->getOperand(1); 5590b57cec5SDimitry Andric switch (BinOp->getOpcode()) { 5600b57cec5SDimitry Andric case Instruction::And: 5610b57cec5SDimitry Andric case Instruction::Or: 5620b57cec5SDimitry Andric case Instruction::Xor: 5630b57cec5SDimitry Andric case Instruction::Add: 5640b57cec5SDimitry Andric case Instruction::Sub: 5650b57cec5SDimitry Andric case Instruction::Mul: { 5660b57cec5SDimitry Andric Constant *C; 5670b57cec5SDimitry Andric if (match(BinOp0, m_Constant(C))) { 5680b57cec5SDimitry Andric // trunc (binop C, X) --> binop (trunc C', X) 5690b57cec5SDimitry Andric Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy); 5700b57cec5SDimitry Andric Value *TruncX = Builder.CreateTrunc(BinOp1, DestTy); 5710b57cec5SDimitry Andric return BinaryOperator::Create(BinOp->getOpcode(), NarrowC, TruncX); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric if (match(BinOp1, m_Constant(C))) { 5740b57cec5SDimitry Andric // trunc (binop X, C) --> binop (trunc X, C') 5750b57cec5SDimitry Andric Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy); 5760b57cec5SDimitry Andric Value *TruncX = Builder.CreateTrunc(BinOp0, DestTy); 5770b57cec5SDimitry Andric return BinaryOperator::Create(BinOp->getOpcode(), TruncX, NarrowC); 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric Value *X; 5800b57cec5SDimitry Andric if (match(BinOp0, m_ZExtOrSExt(m_Value(X))) && X->getType() == DestTy) { 5810b57cec5SDimitry Andric // trunc (binop (ext X), Y) --> binop X, (trunc Y) 5820b57cec5SDimitry Andric Value *NarrowOp1 = Builder.CreateTrunc(BinOp1, DestTy); 5830b57cec5SDimitry Andric return BinaryOperator::Create(BinOp->getOpcode(), X, NarrowOp1); 5840b57cec5SDimitry Andric } 5850b57cec5SDimitry Andric if (match(BinOp1, m_ZExtOrSExt(m_Value(X))) && X->getType() == DestTy) { 5860b57cec5SDimitry Andric // trunc (binop Y, (ext X)) --> binop (trunc Y), X 5870b57cec5SDimitry Andric Value *NarrowOp0 = Builder.CreateTrunc(BinOp0, DestTy); 5880b57cec5SDimitry Andric return BinaryOperator::Create(BinOp->getOpcode(), NarrowOp0, X); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric break; 5910b57cec5SDimitry Andric } 59281ad6265SDimitry Andric case Instruction::LShr: 59381ad6265SDimitry Andric case Instruction::AShr: { 59481ad6265SDimitry Andric // trunc (*shr (trunc A), C) --> trunc(*shr A, C) 59581ad6265SDimitry Andric Value *A; 59681ad6265SDimitry Andric Constant *C; 59781ad6265SDimitry Andric if (match(BinOp0, m_Trunc(m_Value(A))) && match(BinOp1, m_Constant(C))) { 59881ad6265SDimitry Andric unsigned MaxShiftAmt = SrcWidth - DestWidth; 59981ad6265SDimitry Andric // If the shift is small enough, all zero/sign bits created by the shift 60081ad6265SDimitry Andric // are removed by the trunc. 60181ad6265SDimitry Andric if (match(C, m_SpecificInt_ICMP(ICmpInst::ICMP_ULE, 60281ad6265SDimitry Andric APInt(SrcWidth, MaxShiftAmt)))) { 60381ad6265SDimitry Andric auto *OldShift = cast<Instruction>(Trunc.getOperand(0)); 60481ad6265SDimitry Andric bool IsExact = OldShift->isExact(); 6055f757f3fSDimitry Andric if (Constant *ShAmt = ConstantFoldIntegerCast(C, A->getType(), 6065f757f3fSDimitry Andric /*IsSigned*/ true, DL)) { 60781ad6265SDimitry Andric ShAmt = Constant::mergeUndefsWith(ShAmt, C); 60881ad6265SDimitry Andric Value *Shift = 60981ad6265SDimitry Andric OldShift->getOpcode() == Instruction::AShr 61081ad6265SDimitry Andric ? Builder.CreateAShr(A, ShAmt, OldShift->getName(), IsExact) 61181ad6265SDimitry Andric : Builder.CreateLShr(A, ShAmt, OldShift->getName(), IsExact); 61281ad6265SDimitry Andric return CastInst::CreateTruncOrBitCast(Shift, DestTy); 61381ad6265SDimitry Andric } 61481ad6265SDimitry Andric } 6155f757f3fSDimitry Andric } 61681ad6265SDimitry Andric break; 61781ad6265SDimitry Andric } 6180b57cec5SDimitry Andric default: break; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 621e8d8bef9SDimitry Andric if (Instruction *NarrowOr = narrowFunnelShift(Trunc)) 6220b57cec5SDimitry Andric return NarrowOr; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric return nullptr; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric /// Try to narrow the width of a splat shuffle. This could be generalized to any 6280b57cec5SDimitry Andric /// shuffle with a constant operand, but we limit the transform to avoid 6290b57cec5SDimitry Andric /// creating a shuffle type that targets may not be able to lower effectively. 6300b57cec5SDimitry Andric static Instruction *shrinkSplatShuffle(TruncInst &Trunc, 6310b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 6320b57cec5SDimitry Andric auto *Shuf = dyn_cast<ShuffleVectorInst>(Trunc.getOperand(0)); 633fe6060f1SDimitry Andric if (Shuf && Shuf->hasOneUse() && match(Shuf->getOperand(1), m_Undef()) && 634bdd1243dSDimitry Andric all_equal(Shuf->getShuffleMask()) && 6350b57cec5SDimitry Andric Shuf->getType() == Shuf->getOperand(0)->getType()) { 636349cc55cSDimitry Andric // trunc (shuf X, Undef, SplatMask) --> shuf (trunc X), Poison, SplatMask 637349cc55cSDimitry Andric // trunc (shuf X, Poison, SplatMask) --> shuf (trunc X), Poison, SplatMask 6380b57cec5SDimitry Andric Value *NarrowOp = Builder.CreateTrunc(Shuf->getOperand(0), Trunc.getType()); 639349cc55cSDimitry Andric return new ShuffleVectorInst(NarrowOp, Shuf->getShuffleMask()); 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric return nullptr; 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric /// Try to narrow the width of an insert element. This could be generalized for 6460b57cec5SDimitry Andric /// any vector constant, but we limit the transform to insertion into undef to 6470b57cec5SDimitry Andric /// avoid potential backend problems from unsupported insertion widths. This 6480b57cec5SDimitry Andric /// could also be extended to handle the case of inserting a scalar constant 6490b57cec5SDimitry Andric /// into a vector variable. 6500b57cec5SDimitry Andric static Instruction *shrinkInsertElt(CastInst &Trunc, 6510b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 6520b57cec5SDimitry Andric Instruction::CastOps Opcode = Trunc.getOpcode(); 6530b57cec5SDimitry Andric assert((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) && 6540b57cec5SDimitry Andric "Unexpected instruction for shrinking"); 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric auto *InsElt = dyn_cast<InsertElementInst>(Trunc.getOperand(0)); 6570b57cec5SDimitry Andric if (!InsElt || !InsElt->hasOneUse()) 6580b57cec5SDimitry Andric return nullptr; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric Type *DestTy = Trunc.getType(); 6610b57cec5SDimitry Andric Type *DestScalarTy = DestTy->getScalarType(); 6620b57cec5SDimitry Andric Value *VecOp = InsElt->getOperand(0); 6630b57cec5SDimitry Andric Value *ScalarOp = InsElt->getOperand(1); 6640b57cec5SDimitry Andric Value *Index = InsElt->getOperand(2); 6650b57cec5SDimitry Andric 666fe6060f1SDimitry Andric if (match(VecOp, m_Undef())) { 6670b57cec5SDimitry Andric // trunc (inselt undef, X, Index) --> inselt undef, (trunc X), Index 6680b57cec5SDimitry Andric // fptrunc (inselt undef, X, Index) --> inselt undef, (fptrunc X), Index 6690b57cec5SDimitry Andric UndefValue *NarrowUndef = UndefValue::get(DestTy); 6700b57cec5SDimitry Andric Value *NarrowOp = Builder.CreateCast(Opcode, ScalarOp, DestScalarTy); 6710b57cec5SDimitry Andric return InsertElementInst::Create(NarrowUndef, NarrowOp, Index); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric return nullptr; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 677e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) { 6785ffd83dbSDimitry Andric if (Instruction *Result = commonCastTransforms(Trunc)) 6790b57cec5SDimitry Andric return Result; 6800b57cec5SDimitry Andric 6815ffd83dbSDimitry Andric Value *Src = Trunc.getOperand(0); 6825ffd83dbSDimitry Andric Type *DestTy = Trunc.getType(), *SrcTy = Src->getType(); 6835ffd83dbSDimitry Andric unsigned DestWidth = DestTy->getScalarSizeInBits(); 6845ffd83dbSDimitry Andric unsigned SrcWidth = SrcTy->getScalarSizeInBits(); 6850b57cec5SDimitry Andric 6860b57cec5SDimitry Andric // Attempt to truncate the entire input expression tree to the destination 6870b57cec5SDimitry Andric // type. Only do this if the dest type is a simple type, don't convert the 6880b57cec5SDimitry Andric // expression tree to something weird like i93 unless the source is also 6890b57cec5SDimitry Andric // strange. 6900b57cec5SDimitry Andric if ((DestTy->isVectorTy() || shouldChangeType(SrcTy, DestTy)) && 6915ffd83dbSDimitry Andric canEvaluateTruncated(Src, DestTy, *this, &Trunc)) { 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // If this cast is a truncate, evaluting in a different type always 6940b57cec5SDimitry Andric // eliminates the cast, so it is always a win. 6950b57cec5SDimitry Andric LLVM_DEBUG( 6960b57cec5SDimitry Andric dbgs() << "ICE: EvaluateInDifferentType converting expression type" 6970b57cec5SDimitry Andric " to avoid cast: " 6985ffd83dbSDimitry Andric << Trunc << '\n'); 6990b57cec5SDimitry Andric Value *Res = EvaluateInDifferentType(Src, DestTy, false); 7000b57cec5SDimitry Andric assert(Res->getType() == DestTy); 7015ffd83dbSDimitry Andric return replaceInstUsesWith(Trunc, Res); 7025ffd83dbSDimitry Andric } 7035ffd83dbSDimitry Andric 7045ffd83dbSDimitry Andric // For integer types, check if we can shorten the entire input expression to 7055ffd83dbSDimitry Andric // DestWidth * 2, which won't allow removing the truncate, but reducing the 7065ffd83dbSDimitry Andric // width may enable further optimizations, e.g. allowing for larger 7075ffd83dbSDimitry Andric // vectorization factors. 7085ffd83dbSDimitry Andric if (auto *DestITy = dyn_cast<IntegerType>(DestTy)) { 7095ffd83dbSDimitry Andric if (DestWidth * 2 < SrcWidth) { 7105ffd83dbSDimitry Andric auto *NewDestTy = DestITy->getExtendedType(); 7115ffd83dbSDimitry Andric if (shouldChangeType(SrcTy, NewDestTy) && 7125ffd83dbSDimitry Andric canEvaluateTruncated(Src, NewDestTy, *this, &Trunc)) { 7135ffd83dbSDimitry Andric LLVM_DEBUG( 7145ffd83dbSDimitry Andric dbgs() << "ICE: EvaluateInDifferentType converting expression type" 7155ffd83dbSDimitry Andric " to reduce the width of operand of" 7165ffd83dbSDimitry Andric << Trunc << '\n'); 7175ffd83dbSDimitry Andric Value *Res = EvaluateInDifferentType(Src, NewDestTy, false); 7185ffd83dbSDimitry Andric return new TruncInst(Res, DestTy); 7195ffd83dbSDimitry Andric } 7205ffd83dbSDimitry Andric } 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Test if the trunc is the user of a select which is part of a 7240b57cec5SDimitry Andric // minimum or maximum operation. If so, don't do any more simplification. 7250b57cec5SDimitry Andric // Even simplifying demanded bits can break the canonical form of a 7260b57cec5SDimitry Andric // min/max. 7270b57cec5SDimitry Andric Value *LHS, *RHS; 7285ffd83dbSDimitry Andric if (SelectInst *Sel = dyn_cast<SelectInst>(Src)) 7295ffd83dbSDimitry Andric if (matchSelectPattern(Sel, LHS, RHS).Flavor != SPF_UNKNOWN) 7300b57cec5SDimitry Andric return nullptr; 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric // See if we can simplify any instructions used by the input whose sole 7330b57cec5SDimitry Andric // purpose is to compute bits we don't care about. 7345ffd83dbSDimitry Andric if (SimplifyDemandedInstructionBits(Trunc)) 7355ffd83dbSDimitry Andric return &Trunc; 7360b57cec5SDimitry Andric 7375ffd83dbSDimitry Andric if (DestWidth == 1) { 7385ffd83dbSDimitry Andric Value *Zero = Constant::getNullValue(SrcTy); 739*0fca6ea1SDimitry Andric 740*0fca6ea1SDimitry Andric Value *X; 741*0fca6ea1SDimitry Andric const APInt *C1; 742*0fca6ea1SDimitry Andric Constant *C2; 743*0fca6ea1SDimitry Andric if (match(Src, m_OneUse(m_Shr(m_Shl(m_Power2(C1), m_Value(X)), 744*0fca6ea1SDimitry Andric m_ImmConstant(C2))))) { 745*0fca6ea1SDimitry Andric // trunc ((C1 << X) >> C2) to i1 --> X == (C2-cttz(C1)), where C1 is pow2 746*0fca6ea1SDimitry Andric Constant *Log2C1 = ConstantInt::get(SrcTy, C1->exactLogBase2()); 747*0fca6ea1SDimitry Andric Constant *CmpC = ConstantExpr::getSub(C2, Log2C1); 748*0fca6ea1SDimitry Andric return new ICmpInst(ICmpInst::ICMP_EQ, X, CmpC); 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 7515ffd83dbSDimitry Andric Constant *C; 752*0fca6ea1SDimitry Andric if (match(Src, m_OneUse(m_LShr(m_Value(X), m_ImmConstant(C))))) { 7530b57cec5SDimitry Andric // trunc (lshr X, C) to i1 --> icmp ne (and X, C'), 0 7545ffd83dbSDimitry Andric Constant *One = ConstantInt::get(SrcTy, APInt(SrcWidth, 1)); 755*0fca6ea1SDimitry Andric Value *MaskC = Builder.CreateShl(One, C); 7565ffd83dbSDimitry Andric Value *And = Builder.CreateAnd(X, MaskC); 7570b57cec5SDimitry Andric return new ICmpInst(ICmpInst::ICMP_NE, And, Zero); 7580b57cec5SDimitry Andric } 75906c3fb27SDimitry Andric if (match(Src, m_OneUse(m_c_Or(m_LShr(m_Value(X), m_ImmConstant(C)), 7600b57cec5SDimitry Andric m_Deferred(X))))) { 7610b57cec5SDimitry Andric // trunc (or (lshr X, C), X) to i1 --> icmp ne (and X, C'), 0 7625ffd83dbSDimitry Andric Constant *One = ConstantInt::get(SrcTy, APInt(SrcWidth, 1)); 763*0fca6ea1SDimitry Andric Value *MaskC = Builder.CreateShl(One, C); 76406c3fb27SDimitry Andric Value *And = Builder.CreateAnd(X, Builder.CreateOr(MaskC, One)); 7650b57cec5SDimitry Andric return new ICmpInst(ICmpInst::ICMP_NE, And, Zero); 7660b57cec5SDimitry Andric } 767*0fca6ea1SDimitry Andric 768*0fca6ea1SDimitry Andric { 769*0fca6ea1SDimitry Andric const APInt *C; 770*0fca6ea1SDimitry Andric if (match(Src, m_Shl(m_APInt(C), m_Value(X))) && (*C)[0] == 1) { 771*0fca6ea1SDimitry Andric // trunc (C << X) to i1 --> X == 0, where C is odd 772*0fca6ea1SDimitry Andric return new ICmpInst(ICmpInst::Predicate::ICMP_EQ, X, Zero); 773*0fca6ea1SDimitry Andric } 774*0fca6ea1SDimitry Andric } 775*0fca6ea1SDimitry Andric 776*0fca6ea1SDimitry Andric if (Trunc.hasNoUnsignedWrap() || Trunc.hasNoSignedWrap()) { 777*0fca6ea1SDimitry Andric Value *X, *Y; 778*0fca6ea1SDimitry Andric if (match(Src, m_Xor(m_Value(X), m_Value(Y)))) 779*0fca6ea1SDimitry Andric return new ICmpInst(ICmpInst::ICMP_NE, X, Y); 780*0fca6ea1SDimitry Andric } 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric 783fe6060f1SDimitry Andric Value *A, *B; 784e8d8bef9SDimitry Andric Constant *C; 785e8d8bef9SDimitry Andric if (match(Src, m_LShr(m_SExt(m_Value(A)), m_Constant(C)))) { 7865ffd83dbSDimitry Andric unsigned AWidth = A->getType()->getScalarSizeInBits(); 7875ffd83dbSDimitry Andric unsigned MaxShiftAmt = SrcWidth - std::max(DestWidth, AWidth); 788e8d8bef9SDimitry Andric auto *OldSh = cast<Instruction>(Src); 789e8d8bef9SDimitry Andric bool IsExact = OldSh->isExact(); 7900b57cec5SDimitry Andric 7915ffd83dbSDimitry Andric // If the shift is small enough, all zero bits created by the shift are 7925ffd83dbSDimitry Andric // removed by the trunc. 793e8d8bef9SDimitry Andric if (match(C, m_SpecificInt_ICMP(ICmpInst::ICMP_ULE, 794e8d8bef9SDimitry Andric APInt(SrcWidth, MaxShiftAmt)))) { 79506c3fb27SDimitry Andric auto GetNewShAmt = [&](unsigned Width) { 79606c3fb27SDimitry Andric Constant *MaxAmt = ConstantInt::get(SrcTy, Width - 1, false); 79706c3fb27SDimitry Andric Constant *Cmp = 79806c3fb27SDimitry Andric ConstantFoldCompareInstOperands(ICmpInst::ICMP_ULT, C, MaxAmt, DL); 79906c3fb27SDimitry Andric Constant *ShAmt = ConstantFoldSelectInstruction(Cmp, C, MaxAmt); 80006c3fb27SDimitry Andric return ConstantFoldCastOperand(Instruction::Trunc, ShAmt, A->getType(), 80106c3fb27SDimitry Andric DL); 80206c3fb27SDimitry Andric }; 80306c3fb27SDimitry Andric 8045ffd83dbSDimitry Andric // trunc (lshr (sext A), C) --> ashr A, C 8055ffd83dbSDimitry Andric if (A->getType() == DestTy) { 80606c3fb27SDimitry Andric Constant *ShAmt = GetNewShAmt(DestWidth); 807e8d8bef9SDimitry Andric ShAmt = Constant::mergeUndefsWith(ShAmt, C); 808e8d8bef9SDimitry Andric return IsExact ? BinaryOperator::CreateExactAShr(A, ShAmt) 809e8d8bef9SDimitry Andric : BinaryOperator::CreateAShr(A, ShAmt); 8105ffd83dbSDimitry Andric } 8115ffd83dbSDimitry Andric // The types are mismatched, so create a cast after shifting: 8125ffd83dbSDimitry Andric // trunc (lshr (sext A), C) --> sext/trunc (ashr A, C) 8135ffd83dbSDimitry Andric if (Src->hasOneUse()) { 81406c3fb27SDimitry Andric Constant *ShAmt = GetNewShAmt(AWidth); 815e8d8bef9SDimitry Andric Value *Shift = Builder.CreateAShr(A, ShAmt, "", IsExact); 8165ffd83dbSDimitry Andric return CastInst::CreateIntegerCast(Shift, DestTy, true); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric } 8195ffd83dbSDimitry Andric // TODO: Mask high bits with 'and'. 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric 8225ffd83dbSDimitry Andric if (Instruction *I = narrowBinOp(Trunc)) 8230b57cec5SDimitry Andric return I; 8240b57cec5SDimitry Andric 8255ffd83dbSDimitry Andric if (Instruction *I = shrinkSplatShuffle(Trunc, Builder)) 8260b57cec5SDimitry Andric return I; 8270b57cec5SDimitry Andric 8285ffd83dbSDimitry Andric if (Instruction *I = shrinkInsertElt(Trunc, Builder)) 8290b57cec5SDimitry Andric return I; 8300b57cec5SDimitry Andric 831e8d8bef9SDimitry Andric if (Src->hasOneUse() && 832e8d8bef9SDimitry Andric (isa<VectorType>(SrcTy) || shouldChangeType(SrcTy, DestTy))) { 8330b57cec5SDimitry Andric // Transform "trunc (shl X, cst)" -> "shl (trunc X), cst" so long as the 8340b57cec5SDimitry Andric // dest type is native and cst < dest size. 835e8d8bef9SDimitry Andric if (match(Src, m_Shl(m_Value(A), m_Constant(C))) && 8360b57cec5SDimitry Andric !match(A, m_Shr(m_Value(), m_Constant()))) { 8370b57cec5SDimitry Andric // Skip shifts of shift by constants. It undoes a combine in 8380b57cec5SDimitry Andric // FoldShiftByConstant and is the extend in reg pattern. 839e8d8bef9SDimitry Andric APInt Threshold = APInt(C->getType()->getScalarSizeInBits(), DestWidth); 840e8d8bef9SDimitry Andric if (match(C, m_SpecificInt_ICMP(ICmpInst::ICMP_ULT, Threshold))) { 8410b57cec5SDimitry Andric Value *NewTrunc = Builder.CreateTrunc(A, DestTy, A->getName() + ".tr"); 842e8d8bef9SDimitry Andric return BinaryOperator::Create(Instruction::Shl, NewTrunc, 843e8d8bef9SDimitry Andric ConstantExpr::getTrunc(C, DestTy)); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8485ffd83dbSDimitry Andric if (Instruction *I = foldVecTruncToExtElt(Trunc, *this)) 8490b57cec5SDimitry Andric return I; 8500b57cec5SDimitry Andric 8515ffd83dbSDimitry Andric // Whenever an element is extracted from a vector, and then truncated, 8525ffd83dbSDimitry Andric // canonicalize by converting it to a bitcast followed by an 8535ffd83dbSDimitry Andric // extractelement. 8545ffd83dbSDimitry Andric // 8555ffd83dbSDimitry Andric // Example (little endian): 8565ffd83dbSDimitry Andric // trunc (extractelement <4 x i64> %X, 0) to i32 8575ffd83dbSDimitry Andric // ---> 8585ffd83dbSDimitry Andric // extractelement <8 x i32> (bitcast <4 x i64> %X to <8 x i32>), i32 0 8595ffd83dbSDimitry Andric Value *VecOp; 860e8d8bef9SDimitry Andric ConstantInt *Cst; 8615ffd83dbSDimitry Andric if (match(Src, m_OneUse(m_ExtractElt(m_Value(VecOp), m_ConstantInt(Cst))))) { 8625ffd83dbSDimitry Andric auto *VecOpTy = cast<VectorType>(VecOp->getType()); 863e8d8bef9SDimitry Andric auto VecElts = VecOpTy->getElementCount(); 8645ffd83dbSDimitry Andric 8655ffd83dbSDimitry Andric // A badly fit destination size would result in an invalid cast. 8665ffd83dbSDimitry Andric if (SrcWidth % DestWidth == 0) { 8675ffd83dbSDimitry Andric uint64_t TruncRatio = SrcWidth / DestWidth; 868e8d8bef9SDimitry Andric uint64_t BitCastNumElts = VecElts.getKnownMinValue() * TruncRatio; 8695ffd83dbSDimitry Andric uint64_t VecOpIdx = Cst->getZExtValue(); 8705ffd83dbSDimitry Andric uint64_t NewIdx = DL.isBigEndian() ? (VecOpIdx + 1) * TruncRatio - 1 8715ffd83dbSDimitry Andric : VecOpIdx * TruncRatio; 8725ffd83dbSDimitry Andric assert(BitCastNumElts <= std::numeric_limits<uint32_t>::max() && 8735ffd83dbSDimitry Andric "overflow 32-bits"); 8745ffd83dbSDimitry Andric 875e8d8bef9SDimitry Andric auto *BitCastTo = 876e8d8bef9SDimitry Andric VectorType::get(DestTy, BitCastNumElts, VecElts.isScalable()); 8775ffd83dbSDimitry Andric Value *BitCast = Builder.CreateBitCast(VecOp, BitCastTo); 8785ffd83dbSDimitry Andric return ExtractElementInst::Create(BitCast, Builder.getInt32(NewIdx)); 8795ffd83dbSDimitry Andric } 8805ffd83dbSDimitry Andric } 8815ffd83dbSDimitry Andric 882fe6060f1SDimitry Andric // trunc (ctlz_i32(zext(A), B) --> add(ctlz_i16(A, B), C) 883fe6060f1SDimitry Andric if (match(Src, m_OneUse(m_Intrinsic<Intrinsic::ctlz>(m_ZExt(m_Value(A)), 884fe6060f1SDimitry Andric m_Value(B))))) { 885fe6060f1SDimitry Andric unsigned AWidth = A->getType()->getScalarSizeInBits(); 886fe6060f1SDimitry Andric if (AWidth == DestWidth && AWidth > Log2_32(SrcWidth)) { 887fe6060f1SDimitry Andric Value *WidthDiff = ConstantInt::get(A->getType(), SrcWidth - AWidth); 888fe6060f1SDimitry Andric Value *NarrowCtlz = 889fe6060f1SDimitry Andric Builder.CreateIntrinsic(Intrinsic::ctlz, {Trunc.getType()}, {A, B}); 890fe6060f1SDimitry Andric return BinaryOperator::CreateAdd(NarrowCtlz, WidthDiff); 891fe6060f1SDimitry Andric } 892fe6060f1SDimitry Andric } 893349cc55cSDimitry Andric 89406c3fb27SDimitry Andric if (match(Src, m_VScale())) { 895349cc55cSDimitry Andric if (Trunc.getFunction() && 896349cc55cSDimitry Andric Trunc.getFunction()->hasFnAttribute(Attribute::VScaleRange)) { 8970eae32dcSDimitry Andric Attribute Attr = 8980eae32dcSDimitry Andric Trunc.getFunction()->getFnAttribute(Attribute::VScaleRange); 899bdd1243dSDimitry Andric if (std::optional<unsigned> MaxVScale = Attr.getVScaleRangeMax()) { 90081ad6265SDimitry Andric if (Log2_32(*MaxVScale) < DestWidth) { 901349cc55cSDimitry Andric Value *VScale = Builder.CreateVScale(ConstantInt::get(DestTy, 1)); 902349cc55cSDimitry Andric return replaceInstUsesWith(Trunc, VScale); 903349cc55cSDimitry Andric } 904349cc55cSDimitry Andric } 905349cc55cSDimitry Andric } 9060eae32dcSDimitry Andric } 907349cc55cSDimitry Andric 908*0fca6ea1SDimitry Andric bool Changed = false; 909*0fca6ea1SDimitry Andric if (!Trunc.hasNoSignedWrap() && 910*0fca6ea1SDimitry Andric ComputeMaxSignificantBits(Src, /*Depth=*/0, &Trunc) <= DestWidth) { 911*0fca6ea1SDimitry Andric Trunc.setHasNoSignedWrap(true); 912*0fca6ea1SDimitry Andric Changed = true; 913*0fca6ea1SDimitry Andric } 914*0fca6ea1SDimitry Andric if (!Trunc.hasNoUnsignedWrap() && 915*0fca6ea1SDimitry Andric MaskedValueIsZero(Src, APInt::getBitsSetFrom(SrcWidth, DestWidth), 916*0fca6ea1SDimitry Andric /*Depth=*/0, &Trunc)) { 917*0fca6ea1SDimitry Andric Trunc.setHasNoUnsignedWrap(true); 918*0fca6ea1SDimitry Andric Changed = true; 919*0fca6ea1SDimitry Andric } 920*0fca6ea1SDimitry Andric 921*0fca6ea1SDimitry Andric return Changed ? &Trunc : nullptr; 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric 924bdd1243dSDimitry Andric Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp, 925bdd1243dSDimitry Andric ZExtInst &Zext) { 9260b57cec5SDimitry Andric // If we are just checking for a icmp eq of a single bit and zext'ing it 9270b57cec5SDimitry Andric // to an integer, then shift the bit to the appropriate place and then 9280b57cec5SDimitry Andric // cast to integer to avoid the comparison. 92981ad6265SDimitry Andric 93081ad6265SDimitry Andric // FIXME: This set of transforms does not check for extra uses and/or creates 93181ad6265SDimitry Andric // an extra instruction (an optional final cast is not included 93281ad6265SDimitry Andric // in the transform comments). We may also want to favor icmp over 93381ad6265SDimitry Andric // shifts in cases of equal instructions because icmp has better 93481ad6265SDimitry Andric // analysis in general (invert the transform). 93581ad6265SDimitry Andric 9360b57cec5SDimitry Andric const APInt *Op1CV; 937480093f4SDimitry Andric if (match(Cmp->getOperand(1), m_APInt(Op1CV))) { 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric // zext (x <s 0) to i32 --> x>>u31 true if signbit set. 94081ad6265SDimitry Andric if (Cmp->getPredicate() == ICmpInst::ICMP_SLT && Op1CV->isZero()) { 941480093f4SDimitry Andric Value *In = Cmp->getOperand(0); 9420b57cec5SDimitry Andric Value *Sh = ConstantInt::get(In->getType(), 9430b57cec5SDimitry Andric In->getType()->getScalarSizeInBits() - 1); 9440b57cec5SDimitry Andric In = Builder.CreateLShr(In, Sh, In->getName() + ".lobit"); 945480093f4SDimitry Andric if (In->getType() != Zext.getType()) 946480093f4SDimitry Andric In = Builder.CreateIntCast(In, Zext.getType(), false /*ZExt*/); 9470b57cec5SDimitry Andric 948480093f4SDimitry Andric return replaceInstUsesWith(Zext, In); 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric // zext (X == 0) to i32 --> X^1 iff X has only the low bit set. 9520b57cec5SDimitry Andric // zext (X == 0) to i32 --> (X>>1)^1 iff X has only the 2nd bit set. 9530b57cec5SDimitry Andric // zext (X != 0) to i32 --> X iff X has only the low bit set. 9540b57cec5SDimitry Andric // zext (X != 0) to i32 --> X>>1 iff X has only the 2nd bit set. 9550b57cec5SDimitry Andric 9565f757f3fSDimitry Andric if (Op1CV->isZero() && Cmp->isEquality()) { 957bdd1243dSDimitry Andric // Exactly 1 possible 1? But not the high-bit because that is 958bdd1243dSDimitry Andric // canonicalized to this form. 9595f757f3fSDimitry Andric KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext); 9600b57cec5SDimitry Andric APInt KnownZeroMask(~Known.Zero); 9610b57cec5SDimitry Andric uint32_t ShAmt = KnownZeroMask.logBase2(); 9625f757f3fSDimitry Andric bool IsExpectShAmt = KnownZeroMask.isPowerOf2() && 9635f757f3fSDimitry Andric (Zext.getType()->getScalarSizeInBits() != ShAmt + 1); 9645f757f3fSDimitry Andric if (IsExpectShAmt && 9655f757f3fSDimitry Andric (Cmp->getOperand(0)->getType() == Zext.getType() || 9665f757f3fSDimitry Andric Cmp->getPredicate() == ICmpInst::ICMP_NE || ShAmt == 0)) { 967480093f4SDimitry Andric Value *In = Cmp->getOperand(0); 9680b57cec5SDimitry Andric if (ShAmt) { 9690b57cec5SDimitry Andric // Perform a logical shr by shiftamt. 9700b57cec5SDimitry Andric // Insert the shift to put the result in the low bit. 9710b57cec5SDimitry Andric In = Builder.CreateLShr(In, ConstantInt::get(In->getType(), ShAmt), 9720b57cec5SDimitry Andric In->getName() + ".lobit"); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 975bdd1243dSDimitry Andric // Toggle the low bit for "X == 0". 976bdd1243dSDimitry Andric if (Cmp->getPredicate() == ICmpInst::ICMP_EQ) 977bdd1243dSDimitry Andric In = Builder.CreateXor(In, ConstantInt::get(In->getType(), 1)); 9780b57cec5SDimitry Andric 979480093f4SDimitry Andric if (Zext.getType() == In->getType()) 980480093f4SDimitry Andric return replaceInstUsesWith(Zext, In); 9810b57cec5SDimitry Andric 982480093f4SDimitry Andric Value *IntCast = Builder.CreateIntCast(In, Zext.getType(), false); 983480093f4SDimitry Andric return replaceInstUsesWith(Zext, IntCast); 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 988480093f4SDimitry Andric if (Cmp->isEquality() && Zext.getType() == Cmp->getOperand(0)->getType()) { 989fe6060f1SDimitry Andric // Test if a bit is clear/set using a shifted-one mask: 990fe6060f1SDimitry Andric // zext (icmp eq (and X, (1 << ShAmt)), 0) --> and (lshr (not X), ShAmt), 1 991fe6060f1SDimitry Andric // zext (icmp ne (and X, (1 << ShAmt)), 0) --> and (lshr X, ShAmt), 1 992fe6060f1SDimitry Andric Value *X, *ShAmt; 993fe6060f1SDimitry Andric if (Cmp->hasOneUse() && match(Cmp->getOperand(1), m_ZeroInt()) && 994fe6060f1SDimitry Andric match(Cmp->getOperand(0), 995fe6060f1SDimitry Andric m_OneUse(m_c_And(m_Shl(m_One(), m_Value(ShAmt)), m_Value(X))))) { 996fe6060f1SDimitry Andric if (Cmp->getPredicate() == ICmpInst::ICMP_EQ) 997fe6060f1SDimitry Andric X = Builder.CreateNot(X); 998fe6060f1SDimitry Andric Value *Lshr = Builder.CreateLShr(X, ShAmt); 999fe6060f1SDimitry Andric Value *And1 = Builder.CreateAnd(Lshr, ConstantInt::get(X->getType(), 1)); 1000fe6060f1SDimitry Andric return replaceInstUsesWith(Zext, And1); 1001fe6060f1SDimitry Andric } 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric return nullptr; 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric /// Determine if the specified value can be computed in the specified wider type 10080b57cec5SDimitry Andric /// and produce the same low bits. If not, return false. 10090b57cec5SDimitry Andric /// 10100b57cec5SDimitry Andric /// If this function returns true, it can also return a non-zero number of bits 10110b57cec5SDimitry Andric /// (in BitsToClear) which indicates that the value it computes is correct for 10120b57cec5SDimitry Andric /// the zero extend, but that the additional BitsToClear bits need to be zero'd 10130b57cec5SDimitry Andric /// out. For example, to promote something like: 10140b57cec5SDimitry Andric /// 10150b57cec5SDimitry Andric /// %B = trunc i64 %A to i32 10160b57cec5SDimitry Andric /// %C = lshr i32 %B, 8 10170b57cec5SDimitry Andric /// %E = zext i32 %C to i64 10180b57cec5SDimitry Andric /// 10190b57cec5SDimitry Andric /// CanEvaluateZExtd for the 'lshr' will return true, and BitsToClear will be 10200b57cec5SDimitry Andric /// set to 8 to indicate that the promoted value needs to have bits 24-31 10210b57cec5SDimitry Andric /// cleared in addition to bits 32-63. Since an 'and' will be generated to 10220b57cec5SDimitry Andric /// clear the top bits anyway, doing this has no extra cost. 10230b57cec5SDimitry Andric /// 10240b57cec5SDimitry Andric /// This function works on both vectors and scalars. 10250b57cec5SDimitry Andric static bool canEvaluateZExtd(Value *V, Type *Ty, unsigned &BitsToClear, 1026e8d8bef9SDimitry Andric InstCombinerImpl &IC, Instruction *CxtI) { 10270b57cec5SDimitry Andric BitsToClear = 0; 10280b57cec5SDimitry Andric if (canAlwaysEvaluateInType(V, Ty)) 10290b57cec5SDimitry Andric return true; 10300b57cec5SDimitry Andric if (canNotEvaluateInType(V, Ty)) 10310b57cec5SDimitry Andric return false; 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric auto *I = cast<Instruction>(V); 10340b57cec5SDimitry Andric unsigned Tmp; 10350b57cec5SDimitry Andric switch (I->getOpcode()) { 10360b57cec5SDimitry Andric case Instruction::ZExt: // zext(zext(x)) -> zext(x). 10370b57cec5SDimitry Andric case Instruction::SExt: // zext(sext(x)) -> sext(x). 10380b57cec5SDimitry Andric case Instruction::Trunc: // zext(trunc(x)) -> trunc(x) or zext(x) 10390b57cec5SDimitry Andric return true; 10400b57cec5SDimitry Andric case Instruction::And: 10410b57cec5SDimitry Andric case Instruction::Or: 10420b57cec5SDimitry Andric case Instruction::Xor: 10430b57cec5SDimitry Andric case Instruction::Add: 10440b57cec5SDimitry Andric case Instruction::Sub: 10450b57cec5SDimitry Andric case Instruction::Mul: 10460b57cec5SDimitry Andric if (!canEvaluateZExtd(I->getOperand(0), Ty, BitsToClear, IC, CxtI) || 10470b57cec5SDimitry Andric !canEvaluateZExtd(I->getOperand(1), Ty, Tmp, IC, CxtI)) 10480b57cec5SDimitry Andric return false; 10490b57cec5SDimitry Andric // These can all be promoted if neither operand has 'bits to clear'. 10500b57cec5SDimitry Andric if (BitsToClear == 0 && Tmp == 0) 10510b57cec5SDimitry Andric return true; 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric // If the operation is an AND/OR/XOR and the bits to clear are zero in the 10540b57cec5SDimitry Andric // other side, BitsToClear is ok. 10550b57cec5SDimitry Andric if (Tmp == 0 && I->isBitwiseLogicOp()) { 10560b57cec5SDimitry Andric // We use MaskedValueIsZero here for generality, but the case we care 10570b57cec5SDimitry Andric // about the most is constant RHS. 10580b57cec5SDimitry Andric unsigned VSize = V->getType()->getScalarSizeInBits(); 10590b57cec5SDimitry Andric if (IC.MaskedValueIsZero(I->getOperand(1), 10600b57cec5SDimitry Andric APInt::getHighBitsSet(VSize, BitsToClear), 10610b57cec5SDimitry Andric 0, CxtI)) { 10620b57cec5SDimitry Andric // If this is an And instruction and all of the BitsToClear are 10630b57cec5SDimitry Andric // known to be zero we can reset BitsToClear. 10640b57cec5SDimitry Andric if (I->getOpcode() == Instruction::And) 10650b57cec5SDimitry Andric BitsToClear = 0; 10660b57cec5SDimitry Andric return true; 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric // Otherwise, we don't know how to analyze this BitsToClear case yet. 10710b57cec5SDimitry Andric return false; 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric case Instruction::Shl: { 10740b57cec5SDimitry Andric // We can promote shl(x, cst) if we can promote x. Since shl overwrites the 10750b57cec5SDimitry Andric // upper bits we can reduce BitsToClear by the shift amount. 10760b57cec5SDimitry Andric const APInt *Amt; 10770b57cec5SDimitry Andric if (match(I->getOperand(1), m_APInt(Amt))) { 10780b57cec5SDimitry Andric if (!canEvaluateZExtd(I->getOperand(0), Ty, BitsToClear, IC, CxtI)) 10790b57cec5SDimitry Andric return false; 10800b57cec5SDimitry Andric uint64_t ShiftAmt = Amt->getZExtValue(); 10810b57cec5SDimitry Andric BitsToClear = ShiftAmt < BitsToClear ? BitsToClear - ShiftAmt : 0; 10820b57cec5SDimitry Andric return true; 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric return false; 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric case Instruction::LShr: { 10870b57cec5SDimitry Andric // We can promote lshr(x, cst) if we can promote x. This requires the 10880b57cec5SDimitry Andric // ultimate 'and' to clear out the high zero bits we're clearing out though. 10890b57cec5SDimitry Andric const APInt *Amt; 10900b57cec5SDimitry Andric if (match(I->getOperand(1), m_APInt(Amt))) { 10910b57cec5SDimitry Andric if (!canEvaluateZExtd(I->getOperand(0), Ty, BitsToClear, IC, CxtI)) 10920b57cec5SDimitry Andric return false; 10930b57cec5SDimitry Andric BitsToClear += Amt->getZExtValue(); 10940b57cec5SDimitry Andric if (BitsToClear > V->getType()->getScalarSizeInBits()) 10950b57cec5SDimitry Andric BitsToClear = V->getType()->getScalarSizeInBits(); 10960b57cec5SDimitry Andric return true; 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric // Cannot promote variable LSHR. 10990b57cec5SDimitry Andric return false; 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric case Instruction::Select: 11020b57cec5SDimitry Andric if (!canEvaluateZExtd(I->getOperand(1), Ty, Tmp, IC, CxtI) || 11030b57cec5SDimitry Andric !canEvaluateZExtd(I->getOperand(2), Ty, BitsToClear, IC, CxtI) || 11040b57cec5SDimitry Andric // TODO: If important, we could handle the case when the BitsToClear are 11050b57cec5SDimitry Andric // known zero in the disagreeing side. 11060b57cec5SDimitry Andric Tmp != BitsToClear) 11070b57cec5SDimitry Andric return false; 11080b57cec5SDimitry Andric return true; 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric case Instruction::PHI: { 11110b57cec5SDimitry Andric // We can change a phi if we can change all operands. Note that we never 11120b57cec5SDimitry Andric // get into trouble with cyclic PHIs here because we only consider 11130b57cec5SDimitry Andric // instructions with a single use. 11140b57cec5SDimitry Andric PHINode *PN = cast<PHINode>(I); 11150b57cec5SDimitry Andric if (!canEvaluateZExtd(PN->getIncomingValue(0), Ty, BitsToClear, IC, CxtI)) 11160b57cec5SDimitry Andric return false; 11170b57cec5SDimitry Andric for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) 11180b57cec5SDimitry Andric if (!canEvaluateZExtd(PN->getIncomingValue(i), Ty, Tmp, IC, CxtI) || 11190b57cec5SDimitry Andric // TODO: If important, we could handle the case when the BitsToClear 11200b57cec5SDimitry Andric // are known zero in the disagreeing input. 11210b57cec5SDimitry Andric Tmp != BitsToClear) 11220b57cec5SDimitry Andric return false; 11230b57cec5SDimitry Andric return true; 11240b57cec5SDimitry Andric } 112506c3fb27SDimitry Andric case Instruction::Call: 112606c3fb27SDimitry Andric // llvm.vscale() can always be executed in larger type, because the 112706c3fb27SDimitry Andric // value is automatically zero-extended. 112806c3fb27SDimitry Andric if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) 112906c3fb27SDimitry Andric if (II->getIntrinsicID() == Intrinsic::vscale) 113006c3fb27SDimitry Andric return true; 113106c3fb27SDimitry Andric return false; 11320b57cec5SDimitry Andric default: 11330b57cec5SDimitry Andric // TODO: Can handle more cases here. 11340b57cec5SDimitry Andric return false; 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 1138bdd1243dSDimitry Andric Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) { 11390b57cec5SDimitry Andric // If this zero extend is only used by a truncate, let the truncate be 11400b57cec5SDimitry Andric // eliminated before we try to optimize this zext. 114106c3fb27SDimitry Andric if (Zext.hasOneUse() && isa<TruncInst>(Zext.user_back()) && 114206c3fb27SDimitry Andric !isa<Constant>(Zext.getOperand(0))) 11430b57cec5SDimitry Andric return nullptr; 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric // If one of the common conversion will work, do it. 1146bdd1243dSDimitry Andric if (Instruction *Result = commonCastTransforms(Zext)) 11470b57cec5SDimitry Andric return Result; 11480b57cec5SDimitry Andric 1149bdd1243dSDimitry Andric Value *Src = Zext.getOperand(0); 1150bdd1243dSDimitry Andric Type *SrcTy = Src->getType(), *DestTy = Zext.getType(); 11510b57cec5SDimitry Andric 1152*0fca6ea1SDimitry Andric // zext nneg bool x -> 0 1153*0fca6ea1SDimitry Andric if (SrcTy->isIntOrIntVectorTy(1) && Zext.hasNonNeg()) 1154*0fca6ea1SDimitry Andric return replaceInstUsesWith(Zext, Constant::getNullValue(Zext.getType())); 1155*0fca6ea1SDimitry Andric 11560b57cec5SDimitry Andric // Try to extend the entire expression tree to the wide destination type. 11570b57cec5SDimitry Andric unsigned BitsToClear; 11580b57cec5SDimitry Andric if (shouldChangeType(SrcTy, DestTy) && 1159bdd1243dSDimitry Andric canEvaluateZExtd(Src, DestTy, BitsToClear, *this, &Zext)) { 11600b57cec5SDimitry Andric assert(BitsToClear <= SrcTy->getScalarSizeInBits() && 11610b57cec5SDimitry Andric "Can't clear more bits than in SrcTy"); 11620b57cec5SDimitry Andric 11630b57cec5SDimitry Andric // Okay, we can transform this! Insert the new expression now. 11640b57cec5SDimitry Andric LLVM_DEBUG( 11650b57cec5SDimitry Andric dbgs() << "ICE: EvaluateInDifferentType converting expression type" 11660b57cec5SDimitry Andric " to avoid zero extend: " 1167bdd1243dSDimitry Andric << Zext << '\n'); 11680b57cec5SDimitry Andric Value *Res = EvaluateInDifferentType(Src, DestTy, false); 11690b57cec5SDimitry Andric assert(Res->getType() == DestTy); 11700b57cec5SDimitry Andric 11710b57cec5SDimitry Andric // Preserve debug values referring to Src if the zext is its last use. 11720b57cec5SDimitry Andric if (auto *SrcOp = dyn_cast<Instruction>(Src)) 11730b57cec5SDimitry Andric if (SrcOp->hasOneUse()) 1174bdd1243dSDimitry Andric replaceAllDbgUsesWith(*SrcOp, *Res, Zext, DT); 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric uint32_t SrcBitsKept = SrcTy->getScalarSizeInBits() - BitsToClear; 11770b57cec5SDimitry Andric uint32_t DestBitSize = DestTy->getScalarSizeInBits(); 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric // If the high bits are already filled with zeros, just replace this 11800b57cec5SDimitry Andric // cast with the result. 11810b57cec5SDimitry Andric if (MaskedValueIsZero(Res, 11820b57cec5SDimitry Andric APInt::getHighBitsSet(DestBitSize, 11830b57cec5SDimitry Andric DestBitSize - SrcBitsKept), 1184bdd1243dSDimitry Andric 0, &Zext)) 1185bdd1243dSDimitry Andric return replaceInstUsesWith(Zext, Res); 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric // We need to emit an AND to clear the high bits. 11880b57cec5SDimitry Andric Constant *C = ConstantInt::get(Res->getType(), 11890b57cec5SDimitry Andric APInt::getLowBitsSet(DestBitSize, SrcBitsKept)); 11900b57cec5SDimitry Andric return BinaryOperator::CreateAnd(Res, C); 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric // If this is a TRUNC followed by a ZEXT then we are dealing with integral 11940b57cec5SDimitry Andric // types and if the sizes are just right we can convert this into a logical 11950b57cec5SDimitry Andric // 'and' which will be much cheaper than the pair of casts. 1196bdd1243dSDimitry Andric if (auto *CSrc = dyn_cast<TruncInst>(Src)) { // A->B->C cast 11970b57cec5SDimitry Andric // TODO: Subsume this into EvaluateInDifferentType. 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric // Get the sizes of the types involved. We know that the intermediate type 12000b57cec5SDimitry Andric // will be smaller than A or C, but don't know the relation between A and C. 12010b57cec5SDimitry Andric Value *A = CSrc->getOperand(0); 12020b57cec5SDimitry Andric unsigned SrcSize = A->getType()->getScalarSizeInBits(); 12030b57cec5SDimitry Andric unsigned MidSize = CSrc->getType()->getScalarSizeInBits(); 1204bdd1243dSDimitry Andric unsigned DstSize = DestTy->getScalarSizeInBits(); 12050b57cec5SDimitry Andric // If we're actually extending zero bits, then if 12060b57cec5SDimitry Andric // SrcSize < DstSize: zext(a & mask) 12070b57cec5SDimitry Andric // SrcSize == DstSize: a & mask 12080b57cec5SDimitry Andric // SrcSize > DstSize: trunc(a) & mask 12090b57cec5SDimitry Andric if (SrcSize < DstSize) { 12100b57cec5SDimitry Andric APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); 12110b57cec5SDimitry Andric Constant *AndConst = ConstantInt::get(A->getType(), AndValue); 12120b57cec5SDimitry Andric Value *And = Builder.CreateAnd(A, AndConst, CSrc->getName() + ".mask"); 1213bdd1243dSDimitry Andric return new ZExtInst(And, DestTy); 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric if (SrcSize == DstSize) { 12170b57cec5SDimitry Andric APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); 12180b57cec5SDimitry Andric return BinaryOperator::CreateAnd(A, ConstantInt::get(A->getType(), 12190b57cec5SDimitry Andric AndValue)); 12200b57cec5SDimitry Andric } 12210b57cec5SDimitry Andric if (SrcSize > DstSize) { 1222bdd1243dSDimitry Andric Value *Trunc = Builder.CreateTrunc(A, DestTy); 12230b57cec5SDimitry Andric APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize)); 12240b57cec5SDimitry Andric return BinaryOperator::CreateAnd(Trunc, 12250b57cec5SDimitry Andric ConstantInt::get(Trunc->getType(), 12260b57cec5SDimitry Andric AndValue)); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric 1230bdd1243dSDimitry Andric if (auto *Cmp = dyn_cast<ICmpInst>(Src)) 1231bdd1243dSDimitry Andric return transformZExtICmp(Cmp, Zext); 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric // zext(trunc(X) & C) -> (X & zext(C)). 12340b57cec5SDimitry Andric Constant *C; 12350b57cec5SDimitry Andric Value *X; 1236349cc55cSDimitry Andric if (match(Src, m_OneUse(m_And(m_Trunc(m_Value(X)), m_Constant(C)))) && 1237bdd1243dSDimitry Andric X->getType() == DestTy) 12385f757f3fSDimitry Andric return BinaryOperator::CreateAnd(X, Builder.CreateZExt(C, DestTy)); 12390b57cec5SDimitry Andric 12400b57cec5SDimitry Andric // zext((trunc(X) & C) ^ C) -> ((X & zext(C)) ^ zext(C)). 12410b57cec5SDimitry Andric Value *And; 1242349cc55cSDimitry Andric if (match(Src, m_OneUse(m_Xor(m_Value(And), m_Constant(C)))) && 12430b57cec5SDimitry Andric match(And, m_OneUse(m_And(m_Trunc(m_Value(X)), m_Specific(C)))) && 1244bdd1243dSDimitry Andric X->getType() == DestTy) { 12455f757f3fSDimitry Andric Value *ZC = Builder.CreateZExt(C, DestTy); 12460b57cec5SDimitry Andric return BinaryOperator::CreateXor(Builder.CreateAnd(X, ZC), ZC); 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric 1249bdd1243dSDimitry Andric // If we are truncating, masking, and then zexting back to the original type, 1250bdd1243dSDimitry Andric // that's just a mask. This is not handled by canEvaluateZextd if the 1251bdd1243dSDimitry Andric // intermediate values have extra uses. This could be generalized further for 1252bdd1243dSDimitry Andric // a non-constant mask operand. 1253bdd1243dSDimitry Andric // zext (and (trunc X), C) --> and X, (zext C) 1254bdd1243dSDimitry Andric if (match(Src, m_And(m_Trunc(m_Value(X)), m_Constant(C))) && 1255bdd1243dSDimitry Andric X->getType() == DestTy) { 12565f757f3fSDimitry Andric Value *ZextC = Builder.CreateZExt(C, DestTy); 1257bdd1243dSDimitry Andric return BinaryOperator::CreateAnd(X, ZextC); 1258bdd1243dSDimitry Andric } 1259bdd1243dSDimitry Andric 126006c3fb27SDimitry Andric if (match(Src, m_VScale())) { 1261bdd1243dSDimitry Andric if (Zext.getFunction() && 1262bdd1243dSDimitry Andric Zext.getFunction()->hasFnAttribute(Attribute::VScaleRange)) { 1263bdd1243dSDimitry Andric Attribute Attr = 1264bdd1243dSDimitry Andric Zext.getFunction()->getFnAttribute(Attribute::VScaleRange); 1265bdd1243dSDimitry Andric if (std::optional<unsigned> MaxVScale = Attr.getVScaleRangeMax()) { 1266349cc55cSDimitry Andric unsigned TypeWidth = Src->getType()->getScalarSizeInBits(); 126781ad6265SDimitry Andric if (Log2_32(*MaxVScale) < TypeWidth) { 1268349cc55cSDimitry Andric Value *VScale = Builder.CreateVScale(ConstantInt::get(DestTy, 1)); 1269bdd1243dSDimitry Andric return replaceInstUsesWith(Zext, VScale); 1270349cc55cSDimitry Andric } 1271349cc55cSDimitry Andric } 1272349cc55cSDimitry Andric } 12730eae32dcSDimitry Andric } 1274349cc55cSDimitry Andric 12755f757f3fSDimitry Andric if (!Zext.hasNonNeg()) { 12765f757f3fSDimitry Andric // If this zero extend is only used by a shift, add nneg flag. 12775f757f3fSDimitry Andric if (Zext.hasOneUse() && 12785f757f3fSDimitry Andric SrcTy->getScalarSizeInBits() > 12795f757f3fSDimitry Andric Log2_64_Ceil(DestTy->getScalarSizeInBits()) && 12805f757f3fSDimitry Andric match(Zext.user_back(), m_Shift(m_Value(), m_Specific(&Zext)))) { 12815f757f3fSDimitry Andric Zext.setNonNeg(); 12825f757f3fSDimitry Andric return &Zext; 12835f757f3fSDimitry Andric } 12845f757f3fSDimitry Andric 12855f757f3fSDimitry Andric if (isKnownNonNegative(Src, SQ.getWithInstruction(&Zext))) { 12865f757f3fSDimitry Andric Zext.setNonNeg(); 12875f757f3fSDimitry Andric return &Zext; 12885f757f3fSDimitry Andric } 12895f757f3fSDimitry Andric } 12905f757f3fSDimitry Andric 12910b57cec5SDimitry Andric return nullptr; 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric /// Transform (sext icmp) to bitwise / integer operations to eliminate the icmp. 1295bdd1243dSDimitry Andric Instruction *InstCombinerImpl::transformSExtICmp(ICmpInst *Cmp, 1296bdd1243dSDimitry Andric SExtInst &Sext) { 1297bdd1243dSDimitry Andric Value *Op0 = Cmp->getOperand(0), *Op1 = Cmp->getOperand(1); 1298bdd1243dSDimitry Andric ICmpInst::Predicate Pred = Cmp->getPredicate(); 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric // Don't bother if Op1 isn't of vector or integer type. 13010b57cec5SDimitry Andric if (!Op1->getType()->isIntOrIntVectorTy()) 13020b57cec5SDimitry Andric return nullptr; 13030b57cec5SDimitry Andric 1304bdd1243dSDimitry Andric if (Pred == ICmpInst::ICMP_SLT && match(Op1, m_ZeroInt())) { 1305bdd1243dSDimitry Andric // sext (x <s 0) --> ashr x, 31 (all ones if negative) 13060b57cec5SDimitry Andric Value *Sh = ConstantInt::get(Op0->getType(), 13070b57cec5SDimitry Andric Op0->getType()->getScalarSizeInBits() - 1); 13080b57cec5SDimitry Andric Value *In = Builder.CreateAShr(Op0, Sh, Op0->getName() + ".lobit"); 1309bdd1243dSDimitry Andric if (In->getType() != Sext.getType()) 1310bdd1243dSDimitry Andric In = Builder.CreateIntCast(In, Sext.getType(), true /*SExt*/); 13110b57cec5SDimitry Andric 1312bdd1243dSDimitry Andric return replaceInstUsesWith(Sext, In); 13130b57cec5SDimitry Andric } 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) { 13160b57cec5SDimitry Andric // If we know that only one bit of the LHS of the icmp can be set and we 13170b57cec5SDimitry Andric // have an equality comparison with zero or a power of 2, we can transform 13180b57cec5SDimitry Andric // the icmp and sext into bitwise/integer operations. 1319bdd1243dSDimitry Andric if (Cmp->hasOneUse() && 1320bdd1243dSDimitry Andric Cmp->isEquality() && (Op1C->isZero() || Op1C->getValue().isPowerOf2())){ 1321bdd1243dSDimitry Andric KnownBits Known = computeKnownBits(Op0, 0, &Sext); 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric APInt KnownZeroMask(~Known.Zero); 13240b57cec5SDimitry Andric if (KnownZeroMask.isPowerOf2()) { 1325bdd1243dSDimitry Andric Value *In = Cmp->getOperand(0); 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andric // If the icmp tests for a known zero bit we can constant fold it. 13280b57cec5SDimitry Andric if (!Op1C->isZero() && Op1C->getValue() != KnownZeroMask) { 13290b57cec5SDimitry Andric Value *V = Pred == ICmpInst::ICMP_NE ? 1330bdd1243dSDimitry Andric ConstantInt::getAllOnesValue(Sext.getType()) : 1331bdd1243dSDimitry Andric ConstantInt::getNullValue(Sext.getType()); 1332bdd1243dSDimitry Andric return replaceInstUsesWith(Sext, V); 13330b57cec5SDimitry Andric } 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric if (!Op1C->isZero() == (Pred == ICmpInst::ICMP_NE)) { 13360b57cec5SDimitry Andric // sext ((x & 2^n) == 0) -> (x >> n) - 1 13370b57cec5SDimitry Andric // sext ((x & 2^n) != 2^n) -> (x >> n) - 1 133806c3fb27SDimitry Andric unsigned ShiftAmt = KnownZeroMask.countr_zero(); 13390b57cec5SDimitry Andric // Perform a right shift to place the desired bit in the LSB. 13400b57cec5SDimitry Andric if (ShiftAmt) 13410b57cec5SDimitry Andric In = Builder.CreateLShr(In, 13420b57cec5SDimitry Andric ConstantInt::get(In->getType(), ShiftAmt)); 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric // At this point "In" is either 1 or 0. Subtract 1 to turn 13450b57cec5SDimitry Andric // {1, 0} -> {0, -1}. 13460b57cec5SDimitry Andric In = Builder.CreateAdd(In, 13470b57cec5SDimitry Andric ConstantInt::getAllOnesValue(In->getType()), 13480b57cec5SDimitry Andric "sext"); 13490b57cec5SDimitry Andric } else { 13500b57cec5SDimitry Andric // sext ((x & 2^n) != 0) -> (x << bitwidth-n) a>> bitwidth-1 13510b57cec5SDimitry Andric // sext ((x & 2^n) == 2^n) -> (x << bitwidth-n) a>> bitwidth-1 135206c3fb27SDimitry Andric unsigned ShiftAmt = KnownZeroMask.countl_zero(); 13530b57cec5SDimitry Andric // Perform a left shift to place the desired bit in the MSB. 13540b57cec5SDimitry Andric if (ShiftAmt) 13550b57cec5SDimitry Andric In = Builder.CreateShl(In, 13560b57cec5SDimitry Andric ConstantInt::get(In->getType(), ShiftAmt)); 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric // Distribute the bit over the whole bit width. 13590b57cec5SDimitry Andric In = Builder.CreateAShr(In, ConstantInt::get(In->getType(), 13600b57cec5SDimitry Andric KnownZeroMask.getBitWidth() - 1), "sext"); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 1363bdd1243dSDimitry Andric if (Sext.getType() == In->getType()) 1364bdd1243dSDimitry Andric return replaceInstUsesWith(Sext, In); 1365bdd1243dSDimitry Andric return CastInst::CreateIntegerCast(In, Sext.getType(), true/*SExt*/); 13660b57cec5SDimitry Andric } 13670b57cec5SDimitry Andric } 13680b57cec5SDimitry Andric } 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric return nullptr; 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric /// Return true if we can take the specified value and return it as type Ty 13740b57cec5SDimitry Andric /// without inserting any new casts and without changing the value of the common 13750b57cec5SDimitry Andric /// low bits. This is used by code that tries to promote integer operations to 13760b57cec5SDimitry Andric /// a wider types will allow us to eliminate the extension. 13770b57cec5SDimitry Andric /// 13780b57cec5SDimitry Andric /// This function works on both vectors and scalars. 13790b57cec5SDimitry Andric /// 13800b57cec5SDimitry Andric static bool canEvaluateSExtd(Value *V, Type *Ty) { 13810b57cec5SDimitry Andric assert(V->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits() && 13820b57cec5SDimitry Andric "Can't sign extend type to a smaller type"); 13830b57cec5SDimitry Andric if (canAlwaysEvaluateInType(V, Ty)) 13840b57cec5SDimitry Andric return true; 13850b57cec5SDimitry Andric if (canNotEvaluateInType(V, Ty)) 13860b57cec5SDimitry Andric return false; 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric auto *I = cast<Instruction>(V); 13890b57cec5SDimitry Andric switch (I->getOpcode()) { 13900b57cec5SDimitry Andric case Instruction::SExt: // sext(sext(x)) -> sext(x) 13910b57cec5SDimitry Andric case Instruction::ZExt: // sext(zext(x)) -> zext(x) 13920b57cec5SDimitry Andric case Instruction::Trunc: // sext(trunc(x)) -> trunc(x) or sext(x) 13930b57cec5SDimitry Andric return true; 13940b57cec5SDimitry Andric case Instruction::And: 13950b57cec5SDimitry Andric case Instruction::Or: 13960b57cec5SDimitry Andric case Instruction::Xor: 13970b57cec5SDimitry Andric case Instruction::Add: 13980b57cec5SDimitry Andric case Instruction::Sub: 13990b57cec5SDimitry Andric case Instruction::Mul: 14000b57cec5SDimitry Andric // These operators can all arbitrarily be extended if their inputs can. 14010b57cec5SDimitry Andric return canEvaluateSExtd(I->getOperand(0), Ty) && 14020b57cec5SDimitry Andric canEvaluateSExtd(I->getOperand(1), Ty); 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric //case Instruction::Shl: TODO 14050b57cec5SDimitry Andric //case Instruction::LShr: TODO 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric case Instruction::Select: 14080b57cec5SDimitry Andric return canEvaluateSExtd(I->getOperand(1), Ty) && 14090b57cec5SDimitry Andric canEvaluateSExtd(I->getOperand(2), Ty); 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric case Instruction::PHI: { 14120b57cec5SDimitry Andric // We can change a phi if we can change all operands. Note that we never 14130b57cec5SDimitry Andric // get into trouble with cyclic PHIs here because we only consider 14140b57cec5SDimitry Andric // instructions with a single use. 14150b57cec5SDimitry Andric PHINode *PN = cast<PHINode>(I); 14160b57cec5SDimitry Andric for (Value *IncValue : PN->incoming_values()) 14170b57cec5SDimitry Andric if (!canEvaluateSExtd(IncValue, Ty)) return false; 14180b57cec5SDimitry Andric return true; 14190b57cec5SDimitry Andric } 14200b57cec5SDimitry Andric default: 14210b57cec5SDimitry Andric // TODO: Can handle more cases here. 14220b57cec5SDimitry Andric break; 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric return false; 14260b57cec5SDimitry Andric } 14270b57cec5SDimitry Andric 1428bdd1243dSDimitry Andric Instruction *InstCombinerImpl::visitSExt(SExtInst &Sext) { 14290b57cec5SDimitry Andric // If this sign extend is only used by a truncate, let the truncate be 14300b57cec5SDimitry Andric // eliminated before we try to optimize this sext. 1431bdd1243dSDimitry Andric if (Sext.hasOneUse() && isa<TruncInst>(Sext.user_back())) 14320b57cec5SDimitry Andric return nullptr; 14330b57cec5SDimitry Andric 1434bdd1243dSDimitry Andric if (Instruction *I = commonCastTransforms(Sext)) 14350b57cec5SDimitry Andric return I; 14360b57cec5SDimitry Andric 1437bdd1243dSDimitry Andric Value *Src = Sext.getOperand(0); 1438bdd1243dSDimitry Andric Type *SrcTy = Src->getType(), *DestTy = Sext.getType(); 1439fe6060f1SDimitry Andric unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); 1440fe6060f1SDimitry Andric unsigned DestBitSize = DestTy->getScalarSizeInBits(); 14410b57cec5SDimitry Andric 144281ad6265SDimitry Andric // If the value being extended is zero or positive, use a zext instead. 14435f757f3fSDimitry Andric if (isKnownNonNegative(Src, SQ.getWithInstruction(&Sext))) { 14445f757f3fSDimitry Andric auto CI = CastInst::Create(Instruction::ZExt, Src, DestTy); 14455f757f3fSDimitry Andric CI->setNonNeg(true); 14465f757f3fSDimitry Andric return CI; 14475f757f3fSDimitry Andric } 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric // Try to extend the entire expression tree to the wide destination type. 14500b57cec5SDimitry Andric if (shouldChangeType(SrcTy, DestTy) && canEvaluateSExtd(Src, DestTy)) { 14510b57cec5SDimitry Andric // Okay, we can transform this! Insert the new expression now. 14520b57cec5SDimitry Andric LLVM_DEBUG( 14530b57cec5SDimitry Andric dbgs() << "ICE: EvaluateInDifferentType converting expression type" 14540b57cec5SDimitry Andric " to avoid sign extend: " 1455bdd1243dSDimitry Andric << Sext << '\n'); 14560b57cec5SDimitry Andric Value *Res = EvaluateInDifferentType(Src, DestTy, true); 14570b57cec5SDimitry Andric assert(Res->getType() == DestTy); 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric // If the high bits are already filled with sign bit, just replace this 14600b57cec5SDimitry Andric // cast with the result. 1461bdd1243dSDimitry Andric if (ComputeNumSignBits(Res, 0, &Sext) > DestBitSize - SrcBitSize) 1462bdd1243dSDimitry Andric return replaceInstUsesWith(Sext, Res); 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric // We need to emit a shl + ashr to do the sign extend. 14650b57cec5SDimitry Andric Value *ShAmt = ConstantInt::get(DestTy, DestBitSize-SrcBitSize); 14660b57cec5SDimitry Andric return BinaryOperator::CreateAShr(Builder.CreateShl(Res, ShAmt, "sext"), 14670b57cec5SDimitry Andric ShAmt); 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric Value *X; 1471fe6060f1SDimitry Andric if (match(Src, m_Trunc(m_Value(X)))) { 1472fe6060f1SDimitry Andric // If the input has more sign bits than bits truncated, then convert 1473fe6060f1SDimitry Andric // directly to final type. 1474fe6060f1SDimitry Andric unsigned XBitSize = X->getType()->getScalarSizeInBits(); 1475bdd1243dSDimitry Andric if (ComputeNumSignBits(X, 0, &Sext) > XBitSize - SrcBitSize) 1476fe6060f1SDimitry Andric return CastInst::CreateIntegerCast(X, DestTy, /* isSigned */ true); 1477fe6060f1SDimitry Andric 1478fe6060f1SDimitry Andric // If input is a trunc from the destination type, then convert into shifts. 1479fe6060f1SDimitry Andric if (Src->hasOneUse() && X->getType() == DestTy) { 1480fe6060f1SDimitry Andric // sext (trunc X) --> ashr (shl X, C), C 14810b57cec5SDimitry Andric Constant *ShAmt = ConstantInt::get(DestTy, DestBitSize - SrcBitSize); 14820b57cec5SDimitry Andric return BinaryOperator::CreateAShr(Builder.CreateShl(X, ShAmt), ShAmt); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 1485fe6060f1SDimitry Andric // If we are replacing shifted-in high zero bits with sign bits, convert 1486fe6060f1SDimitry Andric // the logic shift to arithmetic shift and eliminate the cast to 1487fe6060f1SDimitry Andric // intermediate type: 1488fe6060f1SDimitry Andric // sext (trunc (lshr Y, C)) --> sext/trunc (ashr Y, C) 1489fe6060f1SDimitry Andric Value *Y; 1490fe6060f1SDimitry Andric if (Src->hasOneUse() && 1491fe6060f1SDimitry Andric match(X, m_LShr(m_Value(Y), 1492*0fca6ea1SDimitry Andric m_SpecificIntAllowPoison(XBitSize - SrcBitSize)))) { 1493fe6060f1SDimitry Andric Value *Ashr = Builder.CreateAShr(Y, XBitSize - SrcBitSize); 1494fe6060f1SDimitry Andric return CastInst::CreateIntegerCast(Ashr, DestTy, /* isSigned */ true); 1495fe6060f1SDimitry Andric } 1496fe6060f1SDimitry Andric } 1497fe6060f1SDimitry Andric 1498bdd1243dSDimitry Andric if (auto *Cmp = dyn_cast<ICmpInst>(Src)) 1499bdd1243dSDimitry Andric return transformSExtICmp(Cmp, Sext); 15000b57cec5SDimitry Andric 15010b57cec5SDimitry Andric // If the input is a shl/ashr pair of a same constant, then this is a sign 15020b57cec5SDimitry Andric // extension from a smaller value. If we could trust arbitrary bitwidth 15030b57cec5SDimitry Andric // integers, we could turn this into a truncate to the smaller bit and then 15040b57cec5SDimitry Andric // use a sext for the whole extension. Since we don't, look deeper and check 15050b57cec5SDimitry Andric // for a truncate. If the source and dest are the same type, eliminate the 15060b57cec5SDimitry Andric // trunc and extend and just do shifts. For example, turn: 15070b57cec5SDimitry Andric // %a = trunc i32 %i to i8 1508e8d8bef9SDimitry Andric // %b = shl i8 %a, C 1509e8d8bef9SDimitry Andric // %c = ashr i8 %b, C 15100b57cec5SDimitry Andric // %d = sext i8 %c to i32 15110b57cec5SDimitry Andric // into: 1512e8d8bef9SDimitry Andric // %a = shl i32 %i, 32-(8-C) 1513e8d8bef9SDimitry Andric // %d = ashr i32 %a, 32-(8-C) 15140b57cec5SDimitry Andric Value *A = nullptr; 15150b57cec5SDimitry Andric // TODO: Eventually this could be subsumed by EvaluateInDifferentType. 15165ffd83dbSDimitry Andric Constant *BA = nullptr, *CA = nullptr; 15175ffd83dbSDimitry Andric if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A)), m_Constant(BA)), 15185f757f3fSDimitry Andric m_ImmConstant(CA))) && 1519e8d8bef9SDimitry Andric BA->isElementWiseEqual(CA) && A->getType() == DestTy) { 15205f757f3fSDimitry Andric Constant *WideCurrShAmt = 15215f757f3fSDimitry Andric ConstantFoldCastOperand(Instruction::SExt, CA, DestTy, DL); 15225f757f3fSDimitry Andric assert(WideCurrShAmt && "Constant folding of ImmConstant cannot fail"); 1523e8d8bef9SDimitry Andric Constant *NumLowbitsLeft = ConstantExpr::getSub( 1524e8d8bef9SDimitry Andric ConstantInt::get(DestTy, SrcTy->getScalarSizeInBits()), WideCurrShAmt); 1525e8d8bef9SDimitry Andric Constant *NewShAmt = ConstantExpr::getSub( 1526e8d8bef9SDimitry Andric ConstantInt::get(DestTy, DestTy->getScalarSizeInBits()), 1527e8d8bef9SDimitry Andric NumLowbitsLeft); 1528e8d8bef9SDimitry Andric NewShAmt = 1529e8d8bef9SDimitry Andric Constant::mergeUndefsWith(Constant::mergeUndefsWith(NewShAmt, BA), CA); 1530bdd1243dSDimitry Andric A = Builder.CreateShl(A, NewShAmt, Sext.getName()); 1531e8d8bef9SDimitry Andric return BinaryOperator::CreateAShr(A, NewShAmt); 15320b57cec5SDimitry Andric } 15330b57cec5SDimitry Andric 1534349cc55cSDimitry Andric // Splatting a bit of constant-index across a value: 1535349cc55cSDimitry Andric // sext (ashr (trunc iN X to iM), M-1) to iN --> ashr (shl X, N-M), N-1 153681ad6265SDimitry Andric // If the dest type is different, use a cast (adjust use check). 1537349cc55cSDimitry Andric if (match(Src, m_OneUse(m_AShr(m_Trunc(m_Value(X)), 153881ad6265SDimitry Andric m_SpecificInt(SrcBitSize - 1))))) { 153981ad6265SDimitry Andric Type *XTy = X->getType(); 154081ad6265SDimitry Andric unsigned XBitSize = XTy->getScalarSizeInBits(); 154181ad6265SDimitry Andric Constant *ShlAmtC = ConstantInt::get(XTy, XBitSize - SrcBitSize); 154281ad6265SDimitry Andric Constant *AshrAmtC = ConstantInt::get(XTy, XBitSize - 1); 154381ad6265SDimitry Andric if (XTy == DestTy) 154481ad6265SDimitry Andric return BinaryOperator::CreateAShr(Builder.CreateShl(X, ShlAmtC), 154581ad6265SDimitry Andric AshrAmtC); 154681ad6265SDimitry Andric if (cast<BinaryOperator>(Src)->getOperand(0)->hasOneUse()) { 154781ad6265SDimitry Andric Value *Ashr = Builder.CreateAShr(Builder.CreateShl(X, ShlAmtC), AshrAmtC); 154881ad6265SDimitry Andric return CastInst::CreateIntegerCast(Ashr, DestTy, /* isSigned */ true); 154981ad6265SDimitry Andric } 1550349cc55cSDimitry Andric } 1551349cc55cSDimitry Andric 155206c3fb27SDimitry Andric if (match(Src, m_VScale())) { 1553bdd1243dSDimitry Andric if (Sext.getFunction() && 1554bdd1243dSDimitry Andric Sext.getFunction()->hasFnAttribute(Attribute::VScaleRange)) { 1555bdd1243dSDimitry Andric Attribute Attr = 1556bdd1243dSDimitry Andric Sext.getFunction()->getFnAttribute(Attribute::VScaleRange); 1557bdd1243dSDimitry Andric if (std::optional<unsigned> MaxVScale = Attr.getVScaleRangeMax()) { 155881ad6265SDimitry Andric if (Log2_32(*MaxVScale) < (SrcBitSize - 1)) { 1559349cc55cSDimitry Andric Value *VScale = Builder.CreateVScale(ConstantInt::get(DestTy, 1)); 1560bdd1243dSDimitry Andric return replaceInstUsesWith(Sext, VScale); 1561349cc55cSDimitry Andric } 1562349cc55cSDimitry Andric } 1563349cc55cSDimitry Andric } 15640eae32dcSDimitry Andric } 1565349cc55cSDimitry Andric 15660b57cec5SDimitry Andric return nullptr; 15670b57cec5SDimitry Andric } 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric /// Return a Constant* for the specified floating-point constant if it fits 15700b57cec5SDimitry Andric /// in the specified FP type without changing its value. 15710b57cec5SDimitry Andric static bool fitsInFPType(ConstantFP *CFP, const fltSemantics &Sem) { 15720b57cec5SDimitry Andric bool losesInfo; 15730b57cec5SDimitry Andric APFloat F = CFP->getValueAPF(); 15740b57cec5SDimitry Andric (void)F.convert(Sem, APFloat::rmNearestTiesToEven, &losesInfo); 15750b57cec5SDimitry Andric return !losesInfo; 15760b57cec5SDimitry Andric } 15770b57cec5SDimitry Andric 1578*0fca6ea1SDimitry Andric static Type *shrinkFPConstant(ConstantFP *CFP, bool PreferBFloat) { 15790b57cec5SDimitry Andric if (CFP->getType() == Type::getPPC_FP128Ty(CFP->getContext())) 15800b57cec5SDimitry Andric return nullptr; // No constant folding of this. 1581*0fca6ea1SDimitry Andric // See if the value can be truncated to bfloat and then reextended. 1582*0fca6ea1SDimitry Andric if (PreferBFloat && fitsInFPType(CFP, APFloat::BFloat())) 1583*0fca6ea1SDimitry Andric return Type::getBFloatTy(CFP->getContext()); 15840b57cec5SDimitry Andric // See if the value can be truncated to half and then reextended. 1585*0fca6ea1SDimitry Andric if (!PreferBFloat && fitsInFPType(CFP, APFloat::IEEEhalf())) 15860b57cec5SDimitry Andric return Type::getHalfTy(CFP->getContext()); 15870b57cec5SDimitry Andric // See if the value can be truncated to float and then reextended. 15880b57cec5SDimitry Andric if (fitsInFPType(CFP, APFloat::IEEEsingle())) 15890b57cec5SDimitry Andric return Type::getFloatTy(CFP->getContext()); 15900b57cec5SDimitry Andric if (CFP->getType()->isDoubleTy()) 15910b57cec5SDimitry Andric return nullptr; // Won't shrink. 15920b57cec5SDimitry Andric if (fitsInFPType(CFP, APFloat::IEEEdouble())) 15930b57cec5SDimitry Andric return Type::getDoubleTy(CFP->getContext()); 15940b57cec5SDimitry Andric // Don't try to shrink to various long double types. 15950b57cec5SDimitry Andric return nullptr; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric // Determine if this is a vector of ConstantFPs and if so, return the minimal 15990b57cec5SDimitry Andric // type we can safely truncate all elements to. 1600*0fca6ea1SDimitry Andric static Type *shrinkFPConstantVector(Value *V, bool PreferBFloat) { 16010b57cec5SDimitry Andric auto *CV = dyn_cast<Constant>(V); 1602fe6060f1SDimitry Andric auto *CVVTy = dyn_cast<FixedVectorType>(V->getType()); 16035ffd83dbSDimitry Andric if (!CV || !CVVTy) 16040b57cec5SDimitry Andric return nullptr; 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric Type *MinType = nullptr; 16070b57cec5SDimitry Andric 1608fe6060f1SDimitry Andric unsigned NumElts = CVVTy->getNumElements(); 1609fe6060f1SDimitry Andric 1610fe6060f1SDimitry Andric // For fixed-width vectors we find the minimal type by looking 1611fe6060f1SDimitry Andric // through the constant values of the vector. 16120b57cec5SDimitry Andric for (unsigned i = 0; i != NumElts; ++i) { 1613bdd1243dSDimitry Andric if (isa<UndefValue>(CV->getAggregateElement(i))) 1614bdd1243dSDimitry Andric continue; 1615bdd1243dSDimitry Andric 16160b57cec5SDimitry Andric auto *CFP = dyn_cast_or_null<ConstantFP>(CV->getAggregateElement(i)); 16170b57cec5SDimitry Andric if (!CFP) 16180b57cec5SDimitry Andric return nullptr; 16190b57cec5SDimitry Andric 1620*0fca6ea1SDimitry Andric Type *T = shrinkFPConstant(CFP, PreferBFloat); 16210b57cec5SDimitry Andric if (!T) 16220b57cec5SDimitry Andric return nullptr; 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric // If we haven't found a type yet or this type has a larger mantissa than 16250b57cec5SDimitry Andric // our previous type, this is our new minimal type. 16260b57cec5SDimitry Andric if (!MinType || T->getFPMantissaWidth() > MinType->getFPMantissaWidth()) 16270b57cec5SDimitry Andric MinType = T; 16280b57cec5SDimitry Andric } 16290b57cec5SDimitry Andric 16300b57cec5SDimitry Andric // Make a vector type from the minimal type. 1631bdd1243dSDimitry Andric return MinType ? FixedVectorType::get(MinType, NumElts) : nullptr; 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric 16340b57cec5SDimitry Andric /// Find the minimum FP type we can safely truncate to. 1635*0fca6ea1SDimitry Andric static Type *getMinimumFPType(Value *V, bool PreferBFloat) { 16360b57cec5SDimitry Andric if (auto *FPExt = dyn_cast<FPExtInst>(V)) 16370b57cec5SDimitry Andric return FPExt->getOperand(0)->getType(); 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric // If this value is a constant, return the constant in the smallest FP type 16400b57cec5SDimitry Andric // that can accurately represent it. This allows us to turn 16410b57cec5SDimitry Andric // (float)((double)X+2.0) into x+2.0f. 16420b57cec5SDimitry Andric if (auto *CFP = dyn_cast<ConstantFP>(V)) 1643*0fca6ea1SDimitry Andric if (Type *T = shrinkFPConstant(CFP, PreferBFloat)) 16440b57cec5SDimitry Andric return T; 16450b57cec5SDimitry Andric 1646fe6060f1SDimitry Andric // We can only correctly find a minimum type for a scalable vector when it is 1647fe6060f1SDimitry Andric // a splat. For splats of constant values the fpext is wrapped up as a 1648fe6060f1SDimitry Andric // ConstantExpr. 1649fe6060f1SDimitry Andric if (auto *FPCExt = dyn_cast<ConstantExpr>(V)) 1650fe6060f1SDimitry Andric if (FPCExt->getOpcode() == Instruction::FPExt) 1651fe6060f1SDimitry Andric return FPCExt->getOperand(0)->getType(); 1652fe6060f1SDimitry Andric 1653fe6060f1SDimitry Andric // Try to shrink a vector of FP constants. This returns nullptr on scalable 1654fe6060f1SDimitry Andric // vectors 1655*0fca6ea1SDimitry Andric if (Type *T = shrinkFPConstantVector(V, PreferBFloat)) 16560b57cec5SDimitry Andric return T; 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric return V->getType(); 16590b57cec5SDimitry Andric } 16600b57cec5SDimitry Andric 16615ffd83dbSDimitry Andric /// Return true if the cast from integer to FP can be proven to be exact for all 16625ffd83dbSDimitry Andric /// possible inputs (the conversion does not lose any precision). 166381ad6265SDimitry Andric static bool isKnownExactCastIntToFP(CastInst &I, InstCombinerImpl &IC) { 16645ffd83dbSDimitry Andric CastInst::CastOps Opcode = I.getOpcode(); 16655ffd83dbSDimitry Andric assert((Opcode == CastInst::SIToFP || Opcode == CastInst::UIToFP) && 16665ffd83dbSDimitry Andric "Unexpected cast"); 16675ffd83dbSDimitry Andric Value *Src = I.getOperand(0); 16685ffd83dbSDimitry Andric Type *SrcTy = Src->getType(); 16695ffd83dbSDimitry Andric Type *FPTy = I.getType(); 16705ffd83dbSDimitry Andric bool IsSigned = Opcode == Instruction::SIToFP; 16715ffd83dbSDimitry Andric int SrcSize = (int)SrcTy->getScalarSizeInBits() - IsSigned; 16725ffd83dbSDimitry Andric 16735ffd83dbSDimitry Andric // Easy case - if the source integer type has less bits than the FP mantissa, 16745ffd83dbSDimitry Andric // then the cast must be exact. 16755ffd83dbSDimitry Andric int DestNumSigBits = FPTy->getFPMantissaWidth(); 16765ffd83dbSDimitry Andric if (SrcSize <= DestNumSigBits) 16775ffd83dbSDimitry Andric return true; 16785ffd83dbSDimitry Andric 16795ffd83dbSDimitry Andric // Cast from FP to integer and back to FP is independent of the intermediate 16805ffd83dbSDimitry Andric // integer width because of poison on overflow. 16815ffd83dbSDimitry Andric Value *F; 16825ffd83dbSDimitry Andric if (match(Src, m_FPToSI(m_Value(F))) || match(Src, m_FPToUI(m_Value(F)))) { 16835ffd83dbSDimitry Andric // If this is uitofp (fptosi F), the source needs an extra bit to avoid 16845ffd83dbSDimitry Andric // potential rounding of negative FP input values. 16855ffd83dbSDimitry Andric int SrcNumSigBits = F->getType()->getFPMantissaWidth(); 16865ffd83dbSDimitry Andric if (!IsSigned && match(Src, m_FPToSI(m_Value()))) 16875ffd83dbSDimitry Andric SrcNumSigBits++; 16885ffd83dbSDimitry Andric 16895ffd83dbSDimitry Andric // [su]itofp (fpto[su]i F) --> exact if the source type has less or equal 16905ffd83dbSDimitry Andric // significant bits than the destination (and make sure neither type is 16915ffd83dbSDimitry Andric // weird -- ppc_fp128). 16925ffd83dbSDimitry Andric if (SrcNumSigBits > 0 && DestNumSigBits > 0 && 16935ffd83dbSDimitry Andric SrcNumSigBits <= DestNumSigBits) 16945ffd83dbSDimitry Andric return true; 16955ffd83dbSDimitry Andric } 16965ffd83dbSDimitry Andric 16975ffd83dbSDimitry Andric // TODO: 16985ffd83dbSDimitry Andric // Try harder to find if the source integer type has less significant bits. 1699753f127fSDimitry Andric // For example, compute number of sign bits. 170081ad6265SDimitry Andric KnownBits SrcKnown = IC.computeKnownBits(Src, 0, &I); 1701753f127fSDimitry Andric int SigBits = (int)SrcTy->getScalarSizeInBits() - 1702753f127fSDimitry Andric SrcKnown.countMinLeadingZeros() - 1703753f127fSDimitry Andric SrcKnown.countMinTrailingZeros(); 1704753f127fSDimitry Andric if (SigBits <= DestNumSigBits) 170581ad6265SDimitry Andric return true; 170681ad6265SDimitry Andric 17075ffd83dbSDimitry Andric return false; 17085ffd83dbSDimitry Andric } 17095ffd83dbSDimitry Andric 1710e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) { 17110b57cec5SDimitry Andric if (Instruction *I = commonCastTransforms(FPT)) 17120b57cec5SDimitry Andric return I; 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric // If we have fptrunc(OpI (fpextend x), (fpextend y)), we would like to 17150b57cec5SDimitry Andric // simplify this expression to avoid one or more of the trunc/extend 17160b57cec5SDimitry Andric // operations if we can do so without changing the numerical results. 17170b57cec5SDimitry Andric // 17180b57cec5SDimitry Andric // The exact manner in which the widths of the operands interact to limit 17190b57cec5SDimitry Andric // what we can and cannot do safely varies from operation to operation, and 17200b57cec5SDimitry Andric // is explained below in the various case statements. 17210b57cec5SDimitry Andric Type *Ty = FPT.getType(); 17228bcb0991SDimitry Andric auto *BO = dyn_cast<BinaryOperator>(FPT.getOperand(0)); 17238bcb0991SDimitry Andric if (BO && BO->hasOneUse()) { 1724*0fca6ea1SDimitry Andric Type *LHSMinType = 1725*0fca6ea1SDimitry Andric getMinimumFPType(BO->getOperand(0), /*PreferBFloat=*/Ty->isBFloatTy()); 1726*0fca6ea1SDimitry Andric Type *RHSMinType = 1727*0fca6ea1SDimitry Andric getMinimumFPType(BO->getOperand(1), /*PreferBFloat=*/Ty->isBFloatTy()); 17288bcb0991SDimitry Andric unsigned OpWidth = BO->getType()->getFPMantissaWidth(); 17290b57cec5SDimitry Andric unsigned LHSWidth = LHSMinType->getFPMantissaWidth(); 17300b57cec5SDimitry Andric unsigned RHSWidth = RHSMinType->getFPMantissaWidth(); 17310b57cec5SDimitry Andric unsigned SrcWidth = std::max(LHSWidth, RHSWidth); 17320b57cec5SDimitry Andric unsigned DstWidth = Ty->getFPMantissaWidth(); 17338bcb0991SDimitry Andric switch (BO->getOpcode()) { 17340b57cec5SDimitry Andric default: break; 17350b57cec5SDimitry Andric case Instruction::FAdd: 17360b57cec5SDimitry Andric case Instruction::FSub: 17370b57cec5SDimitry Andric // For addition and subtraction, the infinitely precise result can 17380b57cec5SDimitry Andric // essentially be arbitrarily wide; proving that double rounding 17390b57cec5SDimitry Andric // will not occur because the result of OpI is exact (as we will for 17400b57cec5SDimitry Andric // FMul, for example) is hopeless. However, we *can* nonetheless 17410b57cec5SDimitry Andric // frequently know that double rounding cannot occur (or that it is 17420b57cec5SDimitry Andric // innocuous) by taking advantage of the specific structure of 17430b57cec5SDimitry Andric // infinitely-precise results that admit double rounding. 17440b57cec5SDimitry Andric // 17450b57cec5SDimitry Andric // Specifically, if OpWidth >= 2*DstWdith+1 and DstWidth is sufficient 17460b57cec5SDimitry Andric // to represent both sources, we can guarantee that the double 17470b57cec5SDimitry Andric // rounding is innocuous (See p50 of Figueroa's 2000 PhD thesis, 17480b57cec5SDimitry Andric // "A Rigorous Framework for Fully Supporting the IEEE Standard ..." 17490b57cec5SDimitry Andric // for proof of this fact). 17500b57cec5SDimitry Andric // 17510b57cec5SDimitry Andric // Note: Figueroa does not consider the case where DstFormat != 17520b57cec5SDimitry Andric // SrcFormat. It's possible (likely even!) that this analysis 17530b57cec5SDimitry Andric // could be tightened for those cases, but they are rare (the main 17540b57cec5SDimitry Andric // case of interest here is (float)((double)float + float)). 17550b57cec5SDimitry Andric if (OpWidth >= 2*DstWidth+1 && DstWidth >= SrcWidth) { 17568bcb0991SDimitry Andric Value *LHS = Builder.CreateFPTrunc(BO->getOperand(0), Ty); 17578bcb0991SDimitry Andric Value *RHS = Builder.CreateFPTrunc(BO->getOperand(1), Ty); 17588bcb0991SDimitry Andric Instruction *RI = BinaryOperator::Create(BO->getOpcode(), LHS, RHS); 17598bcb0991SDimitry Andric RI->copyFastMathFlags(BO); 17600b57cec5SDimitry Andric return RI; 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric break; 17630b57cec5SDimitry Andric case Instruction::FMul: 17640b57cec5SDimitry Andric // For multiplication, the infinitely precise result has at most 17650b57cec5SDimitry Andric // LHSWidth + RHSWidth significant bits; if OpWidth is sufficient 17660b57cec5SDimitry Andric // that such a value can be exactly represented, then no double 17670b57cec5SDimitry Andric // rounding can possibly occur; we can safely perform the operation 17680b57cec5SDimitry Andric // in the destination format if it can represent both sources. 17690b57cec5SDimitry Andric if (OpWidth >= LHSWidth + RHSWidth && DstWidth >= SrcWidth) { 17708bcb0991SDimitry Andric Value *LHS = Builder.CreateFPTrunc(BO->getOperand(0), Ty); 17718bcb0991SDimitry Andric Value *RHS = Builder.CreateFPTrunc(BO->getOperand(1), Ty); 17728bcb0991SDimitry Andric return BinaryOperator::CreateFMulFMF(LHS, RHS, BO); 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric break; 17750b57cec5SDimitry Andric case Instruction::FDiv: 17760b57cec5SDimitry Andric // For division, we use again use the bound from Figueroa's 17770b57cec5SDimitry Andric // dissertation. I am entirely certain that this bound can be 17780b57cec5SDimitry Andric // tightened in the unbalanced operand case by an analysis based on 17790b57cec5SDimitry Andric // the diophantine rational approximation bound, but the well-known 17800b57cec5SDimitry Andric // condition used here is a good conservative first pass. 17810b57cec5SDimitry Andric // TODO: Tighten bound via rigorous analysis of the unbalanced case. 17820b57cec5SDimitry Andric if (OpWidth >= 2*DstWidth && DstWidth >= SrcWidth) { 17838bcb0991SDimitry Andric Value *LHS = Builder.CreateFPTrunc(BO->getOperand(0), Ty); 17848bcb0991SDimitry Andric Value *RHS = Builder.CreateFPTrunc(BO->getOperand(1), Ty); 17858bcb0991SDimitry Andric return BinaryOperator::CreateFDivFMF(LHS, RHS, BO); 17860b57cec5SDimitry Andric } 17870b57cec5SDimitry Andric break; 17880b57cec5SDimitry Andric case Instruction::FRem: { 17890b57cec5SDimitry Andric // Remainder is straightforward. Remainder is always exact, so the 17900b57cec5SDimitry Andric // type of OpI doesn't enter into things at all. We simply evaluate 17910b57cec5SDimitry Andric // in whichever source type is larger, then convert to the 17920b57cec5SDimitry Andric // destination type. 17930b57cec5SDimitry Andric if (SrcWidth == OpWidth) 17940b57cec5SDimitry Andric break; 17950b57cec5SDimitry Andric Value *LHS, *RHS; 17960b57cec5SDimitry Andric if (LHSWidth == SrcWidth) { 17978bcb0991SDimitry Andric LHS = Builder.CreateFPTrunc(BO->getOperand(0), LHSMinType); 17988bcb0991SDimitry Andric RHS = Builder.CreateFPTrunc(BO->getOperand(1), LHSMinType); 17990b57cec5SDimitry Andric } else { 18008bcb0991SDimitry Andric LHS = Builder.CreateFPTrunc(BO->getOperand(0), RHSMinType); 18018bcb0991SDimitry Andric RHS = Builder.CreateFPTrunc(BO->getOperand(1), RHSMinType); 18020b57cec5SDimitry Andric } 18030b57cec5SDimitry Andric 18048bcb0991SDimitry Andric Value *ExactResult = Builder.CreateFRemFMF(LHS, RHS, BO); 18050b57cec5SDimitry Andric return CastInst::CreateFPCast(ExactResult, Ty); 18060b57cec5SDimitry Andric } 18070b57cec5SDimitry Andric } 18080b57cec5SDimitry Andric } 18090b57cec5SDimitry Andric 18100b57cec5SDimitry Andric // (fptrunc (fneg x)) -> (fneg (fptrunc x)) 18110b57cec5SDimitry Andric Value *X; 18120b57cec5SDimitry Andric Instruction *Op = dyn_cast<Instruction>(FPT.getOperand(0)); 18130b57cec5SDimitry Andric if (Op && Op->hasOneUse()) { 1814480093f4SDimitry Andric // FIXME: The FMF should propagate from the fptrunc, not the source op. 1815480093f4SDimitry Andric IRBuilder<>::FastMathFlagGuard FMFG(Builder); 1816480093f4SDimitry Andric if (isa<FPMathOperator>(Op)) 1817480093f4SDimitry Andric Builder.setFastMathFlags(Op->getFastMathFlags()); 1818480093f4SDimitry Andric 18190b57cec5SDimitry Andric if (match(Op, m_FNeg(m_Value(X)))) { 18200b57cec5SDimitry Andric Value *InnerTrunc = Builder.CreateFPTrunc(X, Ty); 18210b57cec5SDimitry Andric 18220b57cec5SDimitry Andric return UnaryOperator::CreateFNegFMF(InnerTrunc, Op); 18230b57cec5SDimitry Andric } 1824480093f4SDimitry Andric 1825480093f4SDimitry Andric // If we are truncating a select that has an extended operand, we can 1826480093f4SDimitry Andric // narrow the other operand and do the select as a narrow op. 1827480093f4SDimitry Andric Value *Cond, *X, *Y; 1828480093f4SDimitry Andric if (match(Op, m_Select(m_Value(Cond), m_FPExt(m_Value(X)), m_Value(Y))) && 1829480093f4SDimitry Andric X->getType() == Ty) { 1830480093f4SDimitry Andric // fptrunc (select Cond, (fpext X), Y --> select Cond, X, (fptrunc Y) 1831480093f4SDimitry Andric Value *NarrowY = Builder.CreateFPTrunc(Y, Ty); 1832480093f4SDimitry Andric Value *Sel = Builder.CreateSelect(Cond, X, NarrowY, "narrow.sel", Op); 1833480093f4SDimitry Andric return replaceInstUsesWith(FPT, Sel); 1834480093f4SDimitry Andric } 1835480093f4SDimitry Andric if (match(Op, m_Select(m_Value(Cond), m_Value(Y), m_FPExt(m_Value(X)))) && 1836480093f4SDimitry Andric X->getType() == Ty) { 1837480093f4SDimitry Andric // fptrunc (select Cond, Y, (fpext X) --> select Cond, (fptrunc Y), X 1838480093f4SDimitry Andric Value *NarrowY = Builder.CreateFPTrunc(Y, Ty); 1839480093f4SDimitry Andric Value *Sel = Builder.CreateSelect(Cond, NarrowY, X, "narrow.sel", Op); 1840480093f4SDimitry Andric return replaceInstUsesWith(FPT, Sel); 1841480093f4SDimitry Andric } 18420b57cec5SDimitry Andric } 18430b57cec5SDimitry Andric 18440b57cec5SDimitry Andric if (auto *II = dyn_cast<IntrinsicInst>(FPT.getOperand(0))) { 18450b57cec5SDimitry Andric switch (II->getIntrinsicID()) { 18460b57cec5SDimitry Andric default: break; 18470b57cec5SDimitry Andric case Intrinsic::ceil: 18480b57cec5SDimitry Andric case Intrinsic::fabs: 18490b57cec5SDimitry Andric case Intrinsic::floor: 18500b57cec5SDimitry Andric case Intrinsic::nearbyint: 18510b57cec5SDimitry Andric case Intrinsic::rint: 18520b57cec5SDimitry Andric case Intrinsic::round: 18535ffd83dbSDimitry Andric case Intrinsic::roundeven: 18540b57cec5SDimitry Andric case Intrinsic::trunc: { 18550b57cec5SDimitry Andric Value *Src = II->getArgOperand(0); 18560b57cec5SDimitry Andric if (!Src->hasOneUse()) 18570b57cec5SDimitry Andric break; 18580b57cec5SDimitry Andric 18590b57cec5SDimitry Andric // Except for fabs, this transformation requires the input of the unary FP 18600b57cec5SDimitry Andric // operation to be itself an fpext from the type to which we're 18610b57cec5SDimitry Andric // truncating. 18620b57cec5SDimitry Andric if (II->getIntrinsicID() != Intrinsic::fabs) { 18630b57cec5SDimitry Andric FPExtInst *FPExtSrc = dyn_cast<FPExtInst>(Src); 18640b57cec5SDimitry Andric if (!FPExtSrc || FPExtSrc->getSrcTy() != Ty) 18650b57cec5SDimitry Andric break; 18660b57cec5SDimitry Andric } 18670b57cec5SDimitry Andric 18680b57cec5SDimitry Andric // Do unary FP operation on smaller type. 18690b57cec5SDimitry Andric // (fptrunc (fabs x)) -> (fabs (fptrunc x)) 18700b57cec5SDimitry Andric Value *InnerTrunc = Builder.CreateFPTrunc(Src, Ty); 18710b57cec5SDimitry Andric Function *Overload = Intrinsic::getDeclaration(FPT.getModule(), 18720b57cec5SDimitry Andric II->getIntrinsicID(), Ty); 18730b57cec5SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles; 18740b57cec5SDimitry Andric II->getOperandBundlesAsDefs(OpBundles); 18750b57cec5SDimitry Andric CallInst *NewCI = 18760b57cec5SDimitry Andric CallInst::Create(Overload, {InnerTrunc}, OpBundles, II->getName()); 18770b57cec5SDimitry Andric NewCI->copyFastMathFlags(II); 18780b57cec5SDimitry Andric return NewCI; 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric if (Instruction *I = shrinkInsertElt(FPT, Builder)) 18840b57cec5SDimitry Andric return I; 18850b57cec5SDimitry Andric 18865ffd83dbSDimitry Andric Value *Src = FPT.getOperand(0); 18875ffd83dbSDimitry Andric if (isa<SIToFPInst>(Src) || isa<UIToFPInst>(Src)) { 18885ffd83dbSDimitry Andric auto *FPCast = cast<CastInst>(Src); 188981ad6265SDimitry Andric if (isKnownExactCastIntToFP(*FPCast, *this)) 18905ffd83dbSDimitry Andric return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty); 18915ffd83dbSDimitry Andric } 18925ffd83dbSDimitry Andric 18930b57cec5SDimitry Andric return nullptr; 18940b57cec5SDimitry Andric } 18950b57cec5SDimitry Andric 1896e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFPExt(CastInst &FPExt) { 18975ffd83dbSDimitry Andric // If the source operand is a cast from integer to FP and known exact, then 18985ffd83dbSDimitry Andric // cast the integer operand directly to the destination type. 18995ffd83dbSDimitry Andric Type *Ty = FPExt.getType(); 19005ffd83dbSDimitry Andric Value *Src = FPExt.getOperand(0); 19015ffd83dbSDimitry Andric if (isa<SIToFPInst>(Src) || isa<UIToFPInst>(Src)) { 19025ffd83dbSDimitry Andric auto *FPCast = cast<CastInst>(Src); 190381ad6265SDimitry Andric if (isKnownExactCastIntToFP(*FPCast, *this)) 19045ffd83dbSDimitry Andric return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty); 19050b57cec5SDimitry Andric } 19060b57cec5SDimitry Andric 19075ffd83dbSDimitry Andric return commonCastTransforms(FPExt); 19085ffd83dbSDimitry Andric } 19095ffd83dbSDimitry Andric 19105ffd83dbSDimitry Andric /// fpto{s/u}i({u/s}itofp(X)) --> X or zext(X) or sext(X) or trunc(X) 19115ffd83dbSDimitry Andric /// This is safe if the intermediate type has enough bits in its mantissa to 19125ffd83dbSDimitry Andric /// accurately represent all values of X. For example, this won't work with 19135ffd83dbSDimitry Andric /// i64 -> float -> i64. 1914e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::foldItoFPtoI(CastInst &FI) { 19150b57cec5SDimitry Andric if (!isa<UIToFPInst>(FI.getOperand(0)) && !isa<SIToFPInst>(FI.getOperand(0))) 19160b57cec5SDimitry Andric return nullptr; 19170b57cec5SDimitry Andric 19185ffd83dbSDimitry Andric auto *OpI = cast<CastInst>(FI.getOperand(0)); 19195ffd83dbSDimitry Andric Value *X = OpI->getOperand(0); 19205ffd83dbSDimitry Andric Type *XType = X->getType(); 19215ffd83dbSDimitry Andric Type *DestType = FI.getType(); 19220b57cec5SDimitry Andric bool IsOutputSigned = isa<FPToSIInst>(FI); 19230b57cec5SDimitry Andric 19240b57cec5SDimitry Andric // Since we can assume the conversion won't overflow, our decision as to 19250b57cec5SDimitry Andric // whether the input will fit in the float should depend on the minimum 19260b57cec5SDimitry Andric // of the input range and output range. 19270b57cec5SDimitry Andric 19280b57cec5SDimitry Andric // This means this is also safe for a signed input and unsigned output, since 19290b57cec5SDimitry Andric // a negative input would lead to undefined behavior. 193081ad6265SDimitry Andric if (!isKnownExactCastIntToFP(*OpI, *this)) { 19315ffd83dbSDimitry Andric // The first cast may not round exactly based on the source integer width 19325ffd83dbSDimitry Andric // and FP width, but the overflow UB rules can still allow this to fold. 19335ffd83dbSDimitry Andric // If the destination type is narrow, that means the intermediate FP value 19345ffd83dbSDimitry Andric // must be large enough to hold the source value exactly. 19355ffd83dbSDimitry Andric // For example, (uint8_t)((float)(uint32_t 16777217) is undefined behavior. 193681ad6265SDimitry Andric int OutputSize = (int)DestType->getScalarSizeInBits(); 19375ffd83dbSDimitry Andric if (OutputSize > OpI->getType()->getFPMantissaWidth()) 19380b57cec5SDimitry Andric return nullptr; 19390b57cec5SDimitry Andric } 19400b57cec5SDimitry Andric 19415ffd83dbSDimitry Andric if (DestType->getScalarSizeInBits() > XType->getScalarSizeInBits()) { 19425ffd83dbSDimitry Andric bool IsInputSigned = isa<SIToFPInst>(OpI); 19435ffd83dbSDimitry Andric if (IsInputSigned && IsOutputSigned) 19445ffd83dbSDimitry Andric return new SExtInst(X, DestType); 19455ffd83dbSDimitry Andric return new ZExtInst(X, DestType); 19465ffd83dbSDimitry Andric } 19475ffd83dbSDimitry Andric if (DestType->getScalarSizeInBits() < XType->getScalarSizeInBits()) 19485ffd83dbSDimitry Andric return new TruncInst(X, DestType); 19490b57cec5SDimitry Andric 19505ffd83dbSDimitry Andric assert(XType == DestType && "Unexpected types for int to FP to int casts"); 19515ffd83dbSDimitry Andric return replaceInstUsesWith(FI, X); 19525ffd83dbSDimitry Andric } 19535ffd83dbSDimitry Andric 1954*0fca6ea1SDimitry Andric static Instruction *foldFPtoI(Instruction &FI, InstCombiner &IC) { 1955*0fca6ea1SDimitry Andric // fpto{u/s}i non-norm --> 0 1956*0fca6ea1SDimitry Andric FPClassTest Mask = 1957*0fca6ea1SDimitry Andric FI.getOpcode() == Instruction::FPToUI ? fcPosNormal : fcNormal; 1958*0fca6ea1SDimitry Andric KnownFPClass FPClass = 1959*0fca6ea1SDimitry Andric computeKnownFPClass(FI.getOperand(0), Mask, /*Depth=*/0, 1960*0fca6ea1SDimitry Andric IC.getSimplifyQuery().getWithInstruction(&FI)); 1961*0fca6ea1SDimitry Andric if (FPClass.isKnownNever(Mask)) 1962*0fca6ea1SDimitry Andric return IC.replaceInstUsesWith(FI, ConstantInt::getNullValue(FI.getType())); 1963*0fca6ea1SDimitry Andric 1964*0fca6ea1SDimitry Andric return nullptr; 1965*0fca6ea1SDimitry Andric } 1966*0fca6ea1SDimitry Andric 1967e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFPToUI(FPToUIInst &FI) { 19685ffd83dbSDimitry Andric if (Instruction *I = foldItoFPtoI(FI)) 19690b57cec5SDimitry Andric return I; 19700b57cec5SDimitry Andric 1971*0fca6ea1SDimitry Andric if (Instruction *I = foldFPtoI(FI, *this)) 1972*0fca6ea1SDimitry Andric return I; 1973*0fca6ea1SDimitry Andric 19740b57cec5SDimitry Andric return commonCastTransforms(FI); 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric 1977e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFPToSI(FPToSIInst &FI) { 19785ffd83dbSDimitry Andric if (Instruction *I = foldItoFPtoI(FI)) 19790b57cec5SDimitry Andric return I; 19800b57cec5SDimitry Andric 1981*0fca6ea1SDimitry Andric if (Instruction *I = foldFPtoI(FI, *this)) 1982*0fca6ea1SDimitry Andric return I; 1983*0fca6ea1SDimitry Andric 19840b57cec5SDimitry Andric return commonCastTransforms(FI); 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric 1987e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitUIToFP(CastInst &CI) { 1988*0fca6ea1SDimitry Andric if (Instruction *R = commonCastTransforms(CI)) 1989*0fca6ea1SDimitry Andric return R; 1990*0fca6ea1SDimitry Andric if (!CI.hasNonNeg() && isKnownNonNegative(CI.getOperand(0), SQ)) { 1991*0fca6ea1SDimitry Andric CI.setNonNeg(); 1992*0fca6ea1SDimitry Andric return &CI; 1993*0fca6ea1SDimitry Andric } 1994*0fca6ea1SDimitry Andric return nullptr; 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric 1997e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitSIToFP(CastInst &CI) { 1998*0fca6ea1SDimitry Andric if (Instruction *R = commonCastTransforms(CI)) 1999*0fca6ea1SDimitry Andric return R; 2000*0fca6ea1SDimitry Andric if (isKnownNonNegative(CI.getOperand(0), SQ)) { 2001*0fca6ea1SDimitry Andric auto *UI = 2002*0fca6ea1SDimitry Andric CastInst::Create(Instruction::UIToFP, CI.getOperand(0), CI.getType()); 2003*0fca6ea1SDimitry Andric UI->setNonNeg(true); 2004*0fca6ea1SDimitry Andric return UI; 2005*0fca6ea1SDimitry Andric } 2006*0fca6ea1SDimitry Andric return nullptr; 20070b57cec5SDimitry Andric } 20080b57cec5SDimitry Andric 2009e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitIntToPtr(IntToPtrInst &CI) { 20100b57cec5SDimitry Andric // If the source integer type is not the intptr_t type for this target, do a 20110b57cec5SDimitry Andric // trunc or zext to the intptr_t type, then inttoptr of it. This allows the 20120b57cec5SDimitry Andric // cast to be exposed to other transforms. 20130b57cec5SDimitry Andric unsigned AS = CI.getAddressSpace(); 20140b57cec5SDimitry Andric if (CI.getOperand(0)->getType()->getScalarSizeInBits() != 20150b57cec5SDimitry Andric DL.getPointerSizeInBits(AS)) { 2016fe6060f1SDimitry Andric Type *Ty = CI.getOperand(0)->getType()->getWithNewType( 2017fe6060f1SDimitry Andric DL.getIntPtrType(CI.getContext(), AS)); 20180b57cec5SDimitry Andric Value *P = Builder.CreateZExtOrTrunc(CI.getOperand(0), Ty); 20190b57cec5SDimitry Andric return new IntToPtrInst(P, CI.getType()); 20200b57cec5SDimitry Andric } 20210b57cec5SDimitry Andric 20220b57cec5SDimitry Andric if (Instruction *I = commonCastTransforms(CI)) 20230b57cec5SDimitry Andric return I; 20240b57cec5SDimitry Andric 20250b57cec5SDimitry Andric return nullptr; 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric 2028e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitPtrToInt(PtrToIntInst &CI) { 20290b57cec5SDimitry Andric // If the destination integer type is not the intptr_t type for this target, 20300b57cec5SDimitry Andric // do a ptrtoint to intptr_t then do a trunc or zext. This allows the cast 20310b57cec5SDimitry Andric // to be exposed to other transforms. 2032e8d8bef9SDimitry Andric Value *SrcOp = CI.getPointerOperand(); 2033fe6060f1SDimitry Andric Type *SrcTy = SrcOp->getType(); 20340b57cec5SDimitry Andric Type *Ty = CI.getType(); 20350b57cec5SDimitry Andric unsigned AS = CI.getPointerAddressSpace(); 2036e8d8bef9SDimitry Andric unsigned TySize = Ty->getScalarSizeInBits(); 2037e8d8bef9SDimitry Andric unsigned PtrSize = DL.getPointerSizeInBits(AS); 2038e8d8bef9SDimitry Andric if (TySize != PtrSize) { 2039fe6060f1SDimitry Andric Type *IntPtrTy = 2040fe6060f1SDimitry Andric SrcTy->getWithNewType(DL.getIntPtrType(CI.getContext(), AS)); 2041e8d8bef9SDimitry Andric Value *P = Builder.CreatePtrToInt(SrcOp, IntPtrTy); 2042e8d8bef9SDimitry Andric return CastInst::CreateIntegerCast(P, Ty, /*isSigned=*/false); 20435ffd83dbSDimitry Andric } 20440b57cec5SDimitry Andric 20455f757f3fSDimitry Andric // (ptrtoint (ptrmask P, M)) 20465f757f3fSDimitry Andric // -> (and (ptrtoint P), M) 20475f757f3fSDimitry Andric // This is generally beneficial as `and` is better supported than `ptrmask`. 20485f757f3fSDimitry Andric Value *Ptr, *Mask; 20495f757f3fSDimitry Andric if (match(SrcOp, m_OneUse(m_Intrinsic<Intrinsic::ptrmask>(m_Value(Ptr), 20505f757f3fSDimitry Andric m_Value(Mask)))) && 20515f757f3fSDimitry Andric Mask->getType() == Ty) 20525f757f3fSDimitry Andric return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask); 20535f757f3fSDimitry Andric 2054*0fca6ea1SDimitry Andric if (auto *GEP = dyn_cast<GEPOperator>(SrcOp)) { 2055349cc55cSDimitry Andric // Fold ptrtoint(gep null, x) to multiply + constant if the GEP has one use. 2056349cc55cSDimitry Andric // While this can increase the number of instructions it doesn't actually 2057349cc55cSDimitry Andric // increase the overall complexity since the arithmetic is just part of 2058349cc55cSDimitry Andric // the GEP otherwise. 2059349cc55cSDimitry Andric if (GEP->hasOneUse() && 2060349cc55cSDimitry Andric isa<ConstantPointerNull>(GEP->getPointerOperand())) { 2061349cc55cSDimitry Andric return replaceInstUsesWith(CI, 2062349cc55cSDimitry Andric Builder.CreateIntCast(EmitGEPOffset(GEP), Ty, 2063349cc55cSDimitry Andric /*isSigned=*/false)); 2064349cc55cSDimitry Andric } 2065*0fca6ea1SDimitry Andric 2066*0fca6ea1SDimitry Andric // (ptrtoint (gep (inttoptr Base), ...)) -> Base + Offset 2067*0fca6ea1SDimitry Andric Value *Base; 2068*0fca6ea1SDimitry Andric if (GEP->hasOneUse() && 2069*0fca6ea1SDimitry Andric match(GEP->getPointerOperand(), m_OneUse(m_IntToPtr(m_Value(Base)))) && 2070*0fca6ea1SDimitry Andric Base->getType() == Ty) { 2071*0fca6ea1SDimitry Andric Value *Offset = EmitGEPOffset(GEP); 2072*0fca6ea1SDimitry Andric auto *NewOp = BinaryOperator::CreateAdd(Base, Offset); 2073*0fca6ea1SDimitry Andric if (GEP->hasNoUnsignedWrap() || 2074*0fca6ea1SDimitry Andric (GEP->hasNoUnsignedSignedWrap() && 2075*0fca6ea1SDimitry Andric isKnownNonNegative(Offset, SQ.getWithInstruction(&CI)))) 2076*0fca6ea1SDimitry Andric NewOp->setHasNoUnsignedWrap(true); 2077*0fca6ea1SDimitry Andric return NewOp; 2078*0fca6ea1SDimitry Andric } 2079349cc55cSDimitry Andric } 2080349cc55cSDimitry Andric 2081e8d8bef9SDimitry Andric Value *Vec, *Scalar, *Index; 2082e8d8bef9SDimitry Andric if (match(SrcOp, m_OneUse(m_InsertElt(m_IntToPtr(m_Value(Vec)), 2083e8d8bef9SDimitry Andric m_Value(Scalar), m_Value(Index)))) && 2084e8d8bef9SDimitry Andric Vec->getType() == Ty) { 2085e8d8bef9SDimitry Andric assert(Vec->getType()->getScalarSizeInBits() == PtrSize && "Wrong type"); 2086e8d8bef9SDimitry Andric // Convert the scalar to int followed by insert to eliminate one cast: 2087e8d8bef9SDimitry Andric // p2i (ins (i2p Vec), Scalar, Index --> ins Vec, (p2i Scalar), Index 2088e8d8bef9SDimitry Andric Value *NewCast = Builder.CreatePtrToInt(Scalar, Ty->getScalarType()); 2089e8d8bef9SDimitry Andric return InsertElementInst::Create(Vec, NewCast, Index); 2090e8d8bef9SDimitry Andric } 2091e8d8bef9SDimitry Andric 20925f757f3fSDimitry Andric return commonCastTransforms(CI); 20930b57cec5SDimitry Andric } 20940b57cec5SDimitry Andric 20950b57cec5SDimitry Andric /// This input value (which is known to have vector type) is being zero extended 2096480093f4SDimitry Andric /// or truncated to the specified vector type. Since the zext/trunc is done 2097480093f4SDimitry Andric /// using an integer type, we have a (bitcast(cast(bitcast))) pattern, 2098480093f4SDimitry Andric /// endianness will impact which end of the vector that is extended or 2099480093f4SDimitry Andric /// truncated. 2100480093f4SDimitry Andric /// 2101480093f4SDimitry Andric /// A vector is always stored with index 0 at the lowest address, which 2102480093f4SDimitry Andric /// corresponds to the most significant bits for a big endian stored integer and 2103480093f4SDimitry Andric /// the least significant bits for little endian. A trunc/zext of an integer 2104480093f4SDimitry Andric /// impacts the big end of the integer. Thus, we need to add/remove elements at 2105480093f4SDimitry Andric /// the front of the vector for big endian targets, and the back of the vector 2106480093f4SDimitry Andric /// for little endian targets. 2107480093f4SDimitry Andric /// 21080b57cec5SDimitry Andric /// Try to replace it with a shuffle (and vector/vector bitcast) if possible. 21090b57cec5SDimitry Andric /// 21100b57cec5SDimitry Andric /// The source and destination vector types may have different element types. 2111e8d8bef9SDimitry Andric static Instruction * 2112e8d8bef9SDimitry Andric optimizeVectorResizeWithIntegerBitCasts(Value *InVal, VectorType *DestTy, 2113e8d8bef9SDimitry Andric InstCombinerImpl &IC) { 21140b57cec5SDimitry Andric // We can only do this optimization if the output is a multiple of the input 21150b57cec5SDimitry Andric // element size, or the input is a multiple of the output element size. 21160b57cec5SDimitry Andric // Convert the input type to have the same element type as the output. 21170b57cec5SDimitry Andric VectorType *SrcTy = cast<VectorType>(InVal->getType()); 21180b57cec5SDimitry Andric 21190b57cec5SDimitry Andric if (SrcTy->getElementType() != DestTy->getElementType()) { 21200b57cec5SDimitry Andric // The input types don't need to be identical, but for now they must be the 21210b57cec5SDimitry Andric // same size. There is no specific reason we couldn't handle things like 21220b57cec5SDimitry Andric // <4 x i16> -> <4 x i32> by bitcasting to <2 x i32> but haven't gotten 21230b57cec5SDimitry Andric // there yet. 21240b57cec5SDimitry Andric if (SrcTy->getElementType()->getPrimitiveSizeInBits() != 21250b57cec5SDimitry Andric DestTy->getElementType()->getPrimitiveSizeInBits()) 21260b57cec5SDimitry Andric return nullptr; 21270b57cec5SDimitry Andric 21285ffd83dbSDimitry Andric SrcTy = 2129e8d8bef9SDimitry Andric FixedVectorType::get(DestTy->getElementType(), 2130e8d8bef9SDimitry Andric cast<FixedVectorType>(SrcTy)->getNumElements()); 21310b57cec5SDimitry Andric InVal = IC.Builder.CreateBitCast(InVal, SrcTy); 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric 2134480093f4SDimitry Andric bool IsBigEndian = IC.getDataLayout().isBigEndian(); 2135e8d8bef9SDimitry Andric unsigned SrcElts = cast<FixedVectorType>(SrcTy)->getNumElements(); 2136e8d8bef9SDimitry Andric unsigned DestElts = cast<FixedVectorType>(DestTy)->getNumElements(); 2137480093f4SDimitry Andric 2138480093f4SDimitry Andric assert(SrcElts != DestElts && "Element counts should be different."); 2139480093f4SDimitry Andric 21400b57cec5SDimitry Andric // Now that the element types match, get the shuffle mask and RHS of the 21410b57cec5SDimitry Andric // shuffle to use, which depends on whether we're increasing or decreasing the 21420b57cec5SDimitry Andric // size of the input. 214381ad6265SDimitry Andric auto ShuffleMaskStorage = llvm::to_vector<16>(llvm::seq<int>(0, SrcElts)); 21445ffd83dbSDimitry Andric ArrayRef<int> ShuffleMask; 21450b57cec5SDimitry Andric Value *V2; 21460b57cec5SDimitry Andric 2147480093f4SDimitry Andric if (SrcElts > DestElts) { 2148480093f4SDimitry Andric // If we're shrinking the number of elements (rewriting an integer 2149480093f4SDimitry Andric // truncate), just shuffle in the elements corresponding to the least 2150349cc55cSDimitry Andric // significant bits from the input and use poison as the second shuffle 2151480093f4SDimitry Andric // input. 2152349cc55cSDimitry Andric V2 = PoisonValue::get(SrcTy); 2153480093f4SDimitry Andric // Make sure the shuffle mask selects the "least significant bits" by 2154480093f4SDimitry Andric // keeping elements from back of the src vector for big endian, and from the 2155480093f4SDimitry Andric // front for little endian. 2156480093f4SDimitry Andric ShuffleMask = ShuffleMaskStorage; 2157480093f4SDimitry Andric if (IsBigEndian) 2158480093f4SDimitry Andric ShuffleMask = ShuffleMask.take_back(DestElts); 2159480093f4SDimitry Andric else 2160480093f4SDimitry Andric ShuffleMask = ShuffleMask.take_front(DestElts); 21610b57cec5SDimitry Andric } else { 2162480093f4SDimitry Andric // If we're increasing the number of elements (rewriting an integer zext), 2163480093f4SDimitry Andric // shuffle in all of the elements from InVal. Fill the rest of the result 2164480093f4SDimitry Andric // elements with zeros from a constant zero. 21650b57cec5SDimitry Andric V2 = Constant::getNullValue(SrcTy); 2166480093f4SDimitry Andric // Use first elt from V2 when indicating zero in the shuffle mask. 2167480093f4SDimitry Andric uint32_t NullElt = SrcElts; 2168480093f4SDimitry Andric // Extend with null values in the "most significant bits" by adding elements 2169480093f4SDimitry Andric // in front of the src vector for big endian, and at the back for little 2170480093f4SDimitry Andric // endian. 2171480093f4SDimitry Andric unsigned DeltaElts = DestElts - SrcElts; 2172480093f4SDimitry Andric if (IsBigEndian) 2173480093f4SDimitry Andric ShuffleMaskStorage.insert(ShuffleMaskStorage.begin(), DeltaElts, NullElt); 2174480093f4SDimitry Andric else 2175480093f4SDimitry Andric ShuffleMaskStorage.append(DeltaElts, NullElt); 2176480093f4SDimitry Andric ShuffleMask = ShuffleMaskStorage; 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric 21795ffd83dbSDimitry Andric return new ShuffleVectorInst(InVal, V2, ShuffleMask); 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric static bool isMultipleOfTypeSize(unsigned Value, Type *Ty) { 21830b57cec5SDimitry Andric return Value % Ty->getPrimitiveSizeInBits() == 0; 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric static unsigned getTypeSizeIndex(unsigned Value, Type *Ty) { 21870b57cec5SDimitry Andric return Value / Ty->getPrimitiveSizeInBits(); 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric 21900b57cec5SDimitry Andric /// V is a value which is inserted into a vector of VecEltTy. 21910b57cec5SDimitry Andric /// Look through the value to see if we can decompose it into 21920b57cec5SDimitry Andric /// insertions into the vector. See the example in the comment for 21930b57cec5SDimitry Andric /// OptimizeIntegerToVectorInsertions for the pattern this handles. 21940b57cec5SDimitry Andric /// The type of V is always a non-zero multiple of VecEltTy's size. 21950b57cec5SDimitry Andric /// Shift is the number of bits between the lsb of V and the lsb of 21960b57cec5SDimitry Andric /// the vector. 21970b57cec5SDimitry Andric /// 21980b57cec5SDimitry Andric /// This returns false if the pattern can't be matched or true if it can, 21990b57cec5SDimitry Andric /// filling in Elements with the elements found here. 22000b57cec5SDimitry Andric static bool collectInsertionElements(Value *V, unsigned Shift, 22010b57cec5SDimitry Andric SmallVectorImpl<Value *> &Elements, 22020b57cec5SDimitry Andric Type *VecEltTy, bool isBigEndian) { 22030b57cec5SDimitry Andric assert(isMultipleOfTypeSize(Shift, VecEltTy) && 22040b57cec5SDimitry Andric "Shift should be a multiple of the element type size"); 22050b57cec5SDimitry Andric 22060b57cec5SDimitry Andric // Undef values never contribute useful bits to the result. 22070b57cec5SDimitry Andric if (isa<UndefValue>(V)) return true; 22080b57cec5SDimitry Andric 22090b57cec5SDimitry Andric // If we got down to a value of the right type, we win, try inserting into the 22100b57cec5SDimitry Andric // right element. 22110b57cec5SDimitry Andric if (V->getType() == VecEltTy) { 22120b57cec5SDimitry Andric // Inserting null doesn't actually insert any elements. 22130b57cec5SDimitry Andric if (Constant *C = dyn_cast<Constant>(V)) 22140b57cec5SDimitry Andric if (C->isNullValue()) 22150b57cec5SDimitry Andric return true; 22160b57cec5SDimitry Andric 22170b57cec5SDimitry Andric unsigned ElementIndex = getTypeSizeIndex(Shift, VecEltTy); 22180b57cec5SDimitry Andric if (isBigEndian) 22190b57cec5SDimitry Andric ElementIndex = Elements.size() - ElementIndex - 1; 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric // Fail if multiple elements are inserted into this slot. 22220b57cec5SDimitry Andric if (Elements[ElementIndex]) 22230b57cec5SDimitry Andric return false; 22240b57cec5SDimitry Andric 22250b57cec5SDimitry Andric Elements[ElementIndex] = V; 22260b57cec5SDimitry Andric return true; 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric if (Constant *C = dyn_cast<Constant>(V)) { 22300b57cec5SDimitry Andric // Figure out the # elements this provides, and bitcast it or slice it up 22310b57cec5SDimitry Andric // as required. 22320b57cec5SDimitry Andric unsigned NumElts = getTypeSizeIndex(C->getType()->getPrimitiveSizeInBits(), 22330b57cec5SDimitry Andric VecEltTy); 22340b57cec5SDimitry Andric // If the constant is the size of a vector element, we just need to bitcast 22350b57cec5SDimitry Andric // it to the right type so it gets properly inserted. 22360b57cec5SDimitry Andric if (NumElts == 1) 22370b57cec5SDimitry Andric return collectInsertionElements(ConstantExpr::getBitCast(C, VecEltTy), 22380b57cec5SDimitry Andric Shift, Elements, VecEltTy, isBigEndian); 22390b57cec5SDimitry Andric 22400b57cec5SDimitry Andric // Okay, this is a constant that covers multiple elements. Slice it up into 22410b57cec5SDimitry Andric // pieces and insert each element-sized piece into the vector. 22420b57cec5SDimitry Andric if (!isa<IntegerType>(C->getType())) 22430b57cec5SDimitry Andric C = ConstantExpr::getBitCast(C, IntegerType::get(V->getContext(), 22440b57cec5SDimitry Andric C->getType()->getPrimitiveSizeInBits())); 22450b57cec5SDimitry Andric unsigned ElementSize = VecEltTy->getPrimitiveSizeInBits(); 22460b57cec5SDimitry Andric Type *ElementIntTy = IntegerType::get(C->getContext(), ElementSize); 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric for (unsigned i = 0; i != NumElts; ++i) { 2249439352acSDimitry Andric unsigned ShiftI = i * ElementSize; 22505f757f3fSDimitry Andric Constant *Piece = ConstantFoldBinaryInstruction( 22515f757f3fSDimitry Andric Instruction::LShr, C, ConstantInt::get(C->getType(), ShiftI)); 22525f757f3fSDimitry Andric if (!Piece) 22535f757f3fSDimitry Andric return false; 22545f757f3fSDimitry Andric 22550b57cec5SDimitry Andric Piece = ConstantExpr::getTrunc(Piece, ElementIntTy); 2256439352acSDimitry Andric if (!collectInsertionElements(Piece, ShiftI + Shift, Elements, VecEltTy, 22570b57cec5SDimitry Andric isBigEndian)) 22580b57cec5SDimitry Andric return false; 22590b57cec5SDimitry Andric } 22600b57cec5SDimitry Andric return true; 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric if (!V->hasOneUse()) return false; 22640b57cec5SDimitry Andric 22650b57cec5SDimitry Andric Instruction *I = dyn_cast<Instruction>(V); 22660b57cec5SDimitry Andric if (!I) return false; 22670b57cec5SDimitry Andric switch (I->getOpcode()) { 22680b57cec5SDimitry Andric default: return false; // Unhandled case. 22690b57cec5SDimitry Andric case Instruction::BitCast: 227081ad6265SDimitry Andric if (I->getOperand(0)->getType()->isVectorTy()) 227181ad6265SDimitry Andric return false; 22720b57cec5SDimitry Andric return collectInsertionElements(I->getOperand(0), Shift, Elements, VecEltTy, 22730b57cec5SDimitry Andric isBigEndian); 22740b57cec5SDimitry Andric case Instruction::ZExt: 22750b57cec5SDimitry Andric if (!isMultipleOfTypeSize( 22760b57cec5SDimitry Andric I->getOperand(0)->getType()->getPrimitiveSizeInBits(), 22770b57cec5SDimitry Andric VecEltTy)) 22780b57cec5SDimitry Andric return false; 22790b57cec5SDimitry Andric return collectInsertionElements(I->getOperand(0), Shift, Elements, VecEltTy, 22800b57cec5SDimitry Andric isBigEndian); 22810b57cec5SDimitry Andric case Instruction::Or: 22820b57cec5SDimitry Andric return collectInsertionElements(I->getOperand(0), Shift, Elements, VecEltTy, 22830b57cec5SDimitry Andric isBigEndian) && 22840b57cec5SDimitry Andric collectInsertionElements(I->getOperand(1), Shift, Elements, VecEltTy, 22850b57cec5SDimitry Andric isBigEndian); 22860b57cec5SDimitry Andric case Instruction::Shl: { 22870b57cec5SDimitry Andric // Must be shifting by a constant that is a multiple of the element size. 22880b57cec5SDimitry Andric ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1)); 22890b57cec5SDimitry Andric if (!CI) return false; 22900b57cec5SDimitry Andric Shift += CI->getZExtValue(); 22910b57cec5SDimitry Andric if (!isMultipleOfTypeSize(Shift, VecEltTy)) return false; 22920b57cec5SDimitry Andric return collectInsertionElements(I->getOperand(0), Shift, Elements, VecEltTy, 22930b57cec5SDimitry Andric isBigEndian); 22940b57cec5SDimitry Andric } 22950b57cec5SDimitry Andric 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric 23000b57cec5SDimitry Andric /// If the input is an 'or' instruction, we may be doing shifts and ors to 23010b57cec5SDimitry Andric /// assemble the elements of the vector manually. 23020b57cec5SDimitry Andric /// Try to rip the code out and replace it with insertelements. This is to 23030b57cec5SDimitry Andric /// optimize code like this: 23040b57cec5SDimitry Andric /// 23050b57cec5SDimitry Andric /// %tmp37 = bitcast float %inc to i32 23060b57cec5SDimitry Andric /// %tmp38 = zext i32 %tmp37 to i64 23070b57cec5SDimitry Andric /// %tmp31 = bitcast float %inc5 to i32 23080b57cec5SDimitry Andric /// %tmp32 = zext i32 %tmp31 to i64 23090b57cec5SDimitry Andric /// %tmp33 = shl i64 %tmp32, 32 23100b57cec5SDimitry Andric /// %ins35 = or i64 %tmp33, %tmp38 23110b57cec5SDimitry Andric /// %tmp43 = bitcast i64 %ins35 to <2 x float> 23120b57cec5SDimitry Andric /// 23130b57cec5SDimitry Andric /// Into two insertelements that do "buildvector{%inc, %inc5}". 23140b57cec5SDimitry Andric static Value *optimizeIntegerToVectorInsertions(BitCastInst &CI, 2315e8d8bef9SDimitry Andric InstCombinerImpl &IC) { 2316e8d8bef9SDimitry Andric auto *DestVecTy = cast<FixedVectorType>(CI.getType()); 23170b57cec5SDimitry Andric Value *IntInput = CI.getOperand(0); 23180b57cec5SDimitry Andric 23190b57cec5SDimitry Andric SmallVector<Value*, 8> Elements(DestVecTy->getNumElements()); 23200b57cec5SDimitry Andric if (!collectInsertionElements(IntInput, 0, Elements, 23210b57cec5SDimitry Andric DestVecTy->getElementType(), 23220b57cec5SDimitry Andric IC.getDataLayout().isBigEndian())) 23230b57cec5SDimitry Andric return nullptr; 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric // If we succeeded, we know that all of the element are specified by Elements 23260b57cec5SDimitry Andric // or are zero if Elements has a null entry. Recast this as a set of 23270b57cec5SDimitry Andric // insertions. 23280b57cec5SDimitry Andric Value *Result = Constant::getNullValue(CI.getType()); 23290b57cec5SDimitry Andric for (unsigned i = 0, e = Elements.size(); i != e; ++i) { 23300b57cec5SDimitry Andric if (!Elements[i]) continue; // Unset element. 23310b57cec5SDimitry Andric 23320b57cec5SDimitry Andric Result = IC.Builder.CreateInsertElement(Result, Elements[i], 23330b57cec5SDimitry Andric IC.Builder.getInt32(i)); 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric 23360b57cec5SDimitry Andric return Result; 23370b57cec5SDimitry Andric } 23380b57cec5SDimitry Andric 23390b57cec5SDimitry Andric /// Canonicalize scalar bitcasts of extracted elements into a bitcast of the 23400b57cec5SDimitry Andric /// vector followed by extract element. The backend tends to handle bitcasts of 23410b57cec5SDimitry Andric /// vectors better than bitcasts of scalars because vector registers are 23420b57cec5SDimitry Andric /// usually not type-specific like scalar integer or scalar floating-point. 23430b57cec5SDimitry Andric static Instruction *canonicalizeBitCastExtElt(BitCastInst &BitCast, 2344e8d8bef9SDimitry Andric InstCombinerImpl &IC) { 234581ad6265SDimitry Andric Value *VecOp, *Index; 234681ad6265SDimitry Andric if (!match(BitCast.getOperand(0), 234781ad6265SDimitry Andric m_OneUse(m_ExtractElt(m_Value(VecOp), m_Value(Index))))) 23480b57cec5SDimitry Andric return nullptr; 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric // The bitcast must be to a vectorizable type, otherwise we can't make a new 23510b57cec5SDimitry Andric // type to extract from. 23520b57cec5SDimitry Andric Type *DestType = BitCast.getType(); 235381ad6265SDimitry Andric VectorType *VecType = cast<VectorType>(VecOp->getType()); 235481ad6265SDimitry Andric if (VectorType::isValidElementType(DestType)) { 235581ad6265SDimitry Andric auto *NewVecType = VectorType::get(DestType, VecType); 235681ad6265SDimitry Andric auto *NewBC = IC.Builder.CreateBitCast(VecOp, NewVecType, "bc"); 235781ad6265SDimitry Andric return ExtractElementInst::Create(NewBC, Index); 235881ad6265SDimitry Andric } 23590b57cec5SDimitry Andric 236081ad6265SDimitry Andric // Only solve DestType is vector to avoid inverse transform in visitBitCast. 236181ad6265SDimitry Andric // bitcast (extractelement <1 x elt>, dest) -> bitcast(<1 x elt>, dest) 236281ad6265SDimitry Andric auto *FixedVType = dyn_cast<FixedVectorType>(VecType); 236381ad6265SDimitry Andric if (DestType->isVectorTy() && FixedVType && FixedVType->getNumElements() == 1) 236481ad6265SDimitry Andric return CastInst::Create(Instruction::BitCast, VecOp, DestType); 236581ad6265SDimitry Andric 236681ad6265SDimitry Andric return nullptr; 23670b57cec5SDimitry Andric } 23680b57cec5SDimitry Andric 23690b57cec5SDimitry Andric /// Change the type of a bitwise logic operation if we can eliminate a bitcast. 23700b57cec5SDimitry Andric static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast, 23710b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 23720b57cec5SDimitry Andric Type *DestTy = BitCast.getType(); 23730b57cec5SDimitry Andric BinaryOperator *BO; 237481ad6265SDimitry Andric 237581ad6265SDimitry Andric if (!match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO))) || 23760b57cec5SDimitry Andric !BO->isBitwiseLogicOp()) 23770b57cec5SDimitry Andric return nullptr; 23780b57cec5SDimitry Andric 23790b57cec5SDimitry Andric // FIXME: This transform is restricted to vector types to avoid backend 23800b57cec5SDimitry Andric // problems caused by creating potentially illegal operations. If a fix-up is 23810b57cec5SDimitry Andric // added to handle that situation, we can remove this check. 23820b57cec5SDimitry Andric if (!DestTy->isVectorTy() || !BO->getType()->isVectorTy()) 23830b57cec5SDimitry Andric return nullptr; 23840b57cec5SDimitry Andric 238581ad6265SDimitry Andric if (DestTy->isFPOrFPVectorTy()) { 238681ad6265SDimitry Andric Value *X, *Y; 238781ad6265SDimitry Andric // bitcast(logic(bitcast(X), bitcast(Y))) -> bitcast'(logic(bitcast'(X), Y)) 238881ad6265SDimitry Andric if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) && 238981ad6265SDimitry Andric match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(Y))))) { 239081ad6265SDimitry Andric if (X->getType()->isFPOrFPVectorTy() && 239181ad6265SDimitry Andric Y->getType()->isIntOrIntVectorTy()) { 239281ad6265SDimitry Andric Value *CastedOp = 239381ad6265SDimitry Andric Builder.CreateBitCast(BO->getOperand(0), Y->getType()); 239481ad6265SDimitry Andric Value *NewBO = Builder.CreateBinOp(BO->getOpcode(), CastedOp, Y); 239581ad6265SDimitry Andric return CastInst::CreateBitOrPointerCast(NewBO, DestTy); 239681ad6265SDimitry Andric } 239781ad6265SDimitry Andric if (X->getType()->isIntOrIntVectorTy() && 239881ad6265SDimitry Andric Y->getType()->isFPOrFPVectorTy()) { 239981ad6265SDimitry Andric Value *CastedOp = 240081ad6265SDimitry Andric Builder.CreateBitCast(BO->getOperand(1), X->getType()); 240181ad6265SDimitry Andric Value *NewBO = Builder.CreateBinOp(BO->getOpcode(), CastedOp, X); 240281ad6265SDimitry Andric return CastInst::CreateBitOrPointerCast(NewBO, DestTy); 240381ad6265SDimitry Andric } 240481ad6265SDimitry Andric } 240581ad6265SDimitry Andric return nullptr; 240681ad6265SDimitry Andric } 240781ad6265SDimitry Andric 240881ad6265SDimitry Andric if (!DestTy->isIntOrIntVectorTy()) 240981ad6265SDimitry Andric return nullptr; 241081ad6265SDimitry Andric 24110b57cec5SDimitry Andric Value *X; 24120b57cec5SDimitry Andric if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) && 24130b57cec5SDimitry Andric X->getType() == DestTy && !isa<Constant>(X)) { 24140b57cec5SDimitry Andric // bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y)) 24150b57cec5SDimitry Andric Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy); 24160b57cec5SDimitry Andric return BinaryOperator::Create(BO->getOpcode(), X, CastedOp1); 24170b57cec5SDimitry Andric } 24180b57cec5SDimitry Andric 24190b57cec5SDimitry Andric if (match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(X)))) && 24200b57cec5SDimitry Andric X->getType() == DestTy && !isa<Constant>(X)) { 24210b57cec5SDimitry Andric // bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X) 24220b57cec5SDimitry Andric Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy); 24230b57cec5SDimitry Andric return BinaryOperator::Create(BO->getOpcode(), CastedOp0, X); 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric // Canonicalize vector bitcasts to come before vector bitwise logic with a 24270b57cec5SDimitry Andric // constant. This eases recognition of special constants for later ops. 24280b57cec5SDimitry Andric // Example: 24290b57cec5SDimitry Andric // icmp u/s (a ^ signmask), (b ^ signmask) --> icmp s/u a, b 24300b57cec5SDimitry Andric Constant *C; 24310b57cec5SDimitry Andric if (match(BO->getOperand(1), m_Constant(C))) { 24320b57cec5SDimitry Andric // bitcast (logic X, C) --> logic (bitcast X, C') 24330b57cec5SDimitry Andric Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy); 24345ffd83dbSDimitry Andric Value *CastedC = Builder.CreateBitCast(C, DestTy); 24350b57cec5SDimitry Andric return BinaryOperator::Create(BO->getOpcode(), CastedOp0, CastedC); 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric 24380b57cec5SDimitry Andric return nullptr; 24390b57cec5SDimitry Andric } 24400b57cec5SDimitry Andric 24410b57cec5SDimitry Andric /// Change the type of a select if we can eliminate a bitcast. 24420b57cec5SDimitry Andric static Instruction *foldBitCastSelect(BitCastInst &BitCast, 24430b57cec5SDimitry Andric InstCombiner::BuilderTy &Builder) { 24440b57cec5SDimitry Andric Value *Cond, *TVal, *FVal; 24450b57cec5SDimitry Andric if (!match(BitCast.getOperand(0), 24460b57cec5SDimitry Andric m_OneUse(m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal))))) 24470b57cec5SDimitry Andric return nullptr; 24480b57cec5SDimitry Andric 24490b57cec5SDimitry Andric // A vector select must maintain the same number of elements in its operands. 24500b57cec5SDimitry Andric Type *CondTy = Cond->getType(); 24510b57cec5SDimitry Andric Type *DestTy = BitCast.getType(); 2452e8d8bef9SDimitry Andric if (auto *CondVTy = dyn_cast<VectorType>(CondTy)) 2453e8d8bef9SDimitry Andric if (!DestTy->isVectorTy() || 2454e8d8bef9SDimitry Andric CondVTy->getElementCount() != 2455e8d8bef9SDimitry Andric cast<VectorType>(DestTy)->getElementCount()) 24560b57cec5SDimitry Andric return nullptr; 24570b57cec5SDimitry Andric 24580b57cec5SDimitry Andric // FIXME: This transform is restricted from changing the select between 24590b57cec5SDimitry Andric // scalars and vectors to avoid backend problems caused by creating 24600b57cec5SDimitry Andric // potentially illegal operations. If a fix-up is added to handle that 24610b57cec5SDimitry Andric // situation, we can remove this check. 24620b57cec5SDimitry Andric if (DestTy->isVectorTy() != TVal->getType()->isVectorTy()) 24630b57cec5SDimitry Andric return nullptr; 24640b57cec5SDimitry Andric 24650b57cec5SDimitry Andric auto *Sel = cast<Instruction>(BitCast.getOperand(0)); 24660b57cec5SDimitry Andric Value *X; 24670b57cec5SDimitry Andric if (match(TVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy && 24680b57cec5SDimitry Andric !isa<Constant>(X)) { 24690b57cec5SDimitry Andric // bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y)) 24700b57cec5SDimitry Andric Value *CastedVal = Builder.CreateBitCast(FVal, DestTy); 24710b57cec5SDimitry Andric return SelectInst::Create(Cond, X, CastedVal, "", nullptr, Sel); 24720b57cec5SDimitry Andric } 24730b57cec5SDimitry Andric 24740b57cec5SDimitry Andric if (match(FVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy && 24750b57cec5SDimitry Andric !isa<Constant>(X)) { 24760b57cec5SDimitry Andric // bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X) 24770b57cec5SDimitry Andric Value *CastedVal = Builder.CreateBitCast(TVal, DestTy); 24780b57cec5SDimitry Andric return SelectInst::Create(Cond, CastedVal, X, "", nullptr, Sel); 24790b57cec5SDimitry Andric } 24800b57cec5SDimitry Andric 24810b57cec5SDimitry Andric return nullptr; 24820b57cec5SDimitry Andric } 24830b57cec5SDimitry Andric 24840b57cec5SDimitry Andric /// Check if all users of CI are StoreInsts. 24850b57cec5SDimitry Andric static bool hasStoreUsersOnly(CastInst &CI) { 24860b57cec5SDimitry Andric for (User *U : CI.users()) { 24870b57cec5SDimitry Andric if (!isa<StoreInst>(U)) 24880b57cec5SDimitry Andric return false; 24890b57cec5SDimitry Andric } 24900b57cec5SDimitry Andric return true; 24910b57cec5SDimitry Andric } 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric /// This function handles following case 24940b57cec5SDimitry Andric /// 24950b57cec5SDimitry Andric /// A -> B cast 24960b57cec5SDimitry Andric /// PHI 24970b57cec5SDimitry Andric /// B -> A cast 24980b57cec5SDimitry Andric /// 24990b57cec5SDimitry Andric /// All the related PHI nodes can be replaced by new PHI nodes with type A. 25000b57cec5SDimitry Andric /// The uses of \p CI can be changed to the new PHI node corresponding to \p PN. 2501e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::optimizeBitCastFromPhi(CastInst &CI, 2502e8d8bef9SDimitry Andric PHINode *PN) { 25030b57cec5SDimitry Andric // BitCast used by Store can be handled in InstCombineLoadStoreAlloca.cpp. 25040b57cec5SDimitry Andric if (hasStoreUsersOnly(CI)) 25050b57cec5SDimitry Andric return nullptr; 25060b57cec5SDimitry Andric 25070b57cec5SDimitry Andric Value *Src = CI.getOperand(0); 25080b57cec5SDimitry Andric Type *SrcTy = Src->getType(); // Type B 25090b57cec5SDimitry Andric Type *DestTy = CI.getType(); // Type A 25100b57cec5SDimitry Andric 25110b57cec5SDimitry Andric SmallVector<PHINode *, 4> PhiWorklist; 25120b57cec5SDimitry Andric SmallSetVector<PHINode *, 4> OldPhiNodes; 25130b57cec5SDimitry Andric 25140b57cec5SDimitry Andric // Find all of the A->B casts and PHI nodes. 25150b57cec5SDimitry Andric // We need to inspect all related PHI nodes, but PHIs can be cyclic, so 25160b57cec5SDimitry Andric // OldPhiNodes is used to track all known PHI nodes, before adding a new 25170b57cec5SDimitry Andric // PHI to PhiWorklist, it is checked against and added to OldPhiNodes first. 25180b57cec5SDimitry Andric PhiWorklist.push_back(PN); 25190b57cec5SDimitry Andric OldPhiNodes.insert(PN); 25200b57cec5SDimitry Andric while (!PhiWorklist.empty()) { 25210b57cec5SDimitry Andric auto *OldPN = PhiWorklist.pop_back_val(); 25220b57cec5SDimitry Andric for (Value *IncValue : OldPN->incoming_values()) { 25230b57cec5SDimitry Andric if (isa<Constant>(IncValue)) 25240b57cec5SDimitry Andric continue; 25250b57cec5SDimitry Andric 25260b57cec5SDimitry Andric if (auto *LI = dyn_cast<LoadInst>(IncValue)) { 25270b57cec5SDimitry Andric // If there is a sequence of one or more load instructions, each loaded 25280b57cec5SDimitry Andric // value is used as address of later load instruction, bitcast is 25290b57cec5SDimitry Andric // necessary to change the value type, don't optimize it. For 25300b57cec5SDimitry Andric // simplicity we give up if the load address comes from another load. 25310b57cec5SDimitry Andric Value *Addr = LI->getOperand(0); 25320b57cec5SDimitry Andric if (Addr == &CI || isa<LoadInst>(Addr)) 25330b57cec5SDimitry Andric return nullptr; 2534fe6060f1SDimitry Andric // Don't tranform "load <256 x i32>, <256 x i32>*" to 2535fe6060f1SDimitry Andric // "load x86_amx, x86_amx*", because x86_amx* is invalid. 2536fe6060f1SDimitry Andric // TODO: Remove this check when bitcast between vector and x86_amx 2537fe6060f1SDimitry Andric // is replaced with a specific intrinsic. 2538fe6060f1SDimitry Andric if (DestTy->isX86_AMXTy()) 2539fe6060f1SDimitry Andric return nullptr; 25400b57cec5SDimitry Andric if (LI->hasOneUse() && LI->isSimple()) 25410b57cec5SDimitry Andric continue; 25420b57cec5SDimitry Andric // If a LoadInst has more than one use, changing the type of loaded 25430b57cec5SDimitry Andric // value may create another bitcast. 25440b57cec5SDimitry Andric return nullptr; 25450b57cec5SDimitry Andric } 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric if (auto *PNode = dyn_cast<PHINode>(IncValue)) { 25480b57cec5SDimitry Andric if (OldPhiNodes.insert(PNode)) 25490b57cec5SDimitry Andric PhiWorklist.push_back(PNode); 25500b57cec5SDimitry Andric continue; 25510b57cec5SDimitry Andric } 25520b57cec5SDimitry Andric 25530b57cec5SDimitry Andric auto *BCI = dyn_cast<BitCastInst>(IncValue); 25540b57cec5SDimitry Andric // We can't handle other instructions. 25550b57cec5SDimitry Andric if (!BCI) 25560b57cec5SDimitry Andric return nullptr; 25570b57cec5SDimitry Andric 25580b57cec5SDimitry Andric // Verify it's a A->B cast. 25590b57cec5SDimitry Andric Type *TyA = BCI->getOperand(0)->getType(); 25600b57cec5SDimitry Andric Type *TyB = BCI->getType(); 25610b57cec5SDimitry Andric if (TyA != DestTy || TyB != SrcTy) 25620b57cec5SDimitry Andric return nullptr; 25630b57cec5SDimitry Andric } 25640b57cec5SDimitry Andric } 25650b57cec5SDimitry Andric 2566480093f4SDimitry Andric // Check that each user of each old PHI node is something that we can 2567480093f4SDimitry Andric // rewrite, so that all of the old PHI nodes can be cleaned up afterwards. 2568480093f4SDimitry Andric for (auto *OldPN : OldPhiNodes) { 2569480093f4SDimitry Andric for (User *V : OldPN->users()) { 2570480093f4SDimitry Andric if (auto *SI = dyn_cast<StoreInst>(V)) { 2571480093f4SDimitry Andric if (!SI->isSimple() || SI->getOperand(0) != OldPN) 2572480093f4SDimitry Andric return nullptr; 2573480093f4SDimitry Andric } else if (auto *BCI = dyn_cast<BitCastInst>(V)) { 2574480093f4SDimitry Andric // Verify it's a B->A cast. 2575480093f4SDimitry Andric Type *TyB = BCI->getOperand(0)->getType(); 2576480093f4SDimitry Andric Type *TyA = BCI->getType(); 2577480093f4SDimitry Andric if (TyA != DestTy || TyB != SrcTy) 2578480093f4SDimitry Andric return nullptr; 2579480093f4SDimitry Andric } else if (auto *PHI = dyn_cast<PHINode>(V)) { 2580480093f4SDimitry Andric // As long as the user is another old PHI node, then even if we don't 2581480093f4SDimitry Andric // rewrite it, the PHI web we're considering won't have any users 2582480093f4SDimitry Andric // outside itself, so it'll be dead. 2583349cc55cSDimitry Andric if (!OldPhiNodes.contains(PHI)) 2584480093f4SDimitry Andric return nullptr; 2585480093f4SDimitry Andric } else { 2586480093f4SDimitry Andric return nullptr; 2587480093f4SDimitry Andric } 2588480093f4SDimitry Andric } 2589480093f4SDimitry Andric } 2590480093f4SDimitry Andric 25910b57cec5SDimitry Andric // For each old PHI node, create a corresponding new PHI node with a type A. 25920b57cec5SDimitry Andric SmallDenseMap<PHINode *, PHINode *> NewPNodes; 25930b57cec5SDimitry Andric for (auto *OldPN : OldPhiNodes) { 25940b57cec5SDimitry Andric Builder.SetInsertPoint(OldPN); 25950b57cec5SDimitry Andric PHINode *NewPN = Builder.CreatePHI(DestTy, OldPN->getNumOperands()); 25960b57cec5SDimitry Andric NewPNodes[OldPN] = NewPN; 25970b57cec5SDimitry Andric } 25980b57cec5SDimitry Andric 25990b57cec5SDimitry Andric // Fill in the operands of new PHI nodes. 26000b57cec5SDimitry Andric for (auto *OldPN : OldPhiNodes) { 26010b57cec5SDimitry Andric PHINode *NewPN = NewPNodes[OldPN]; 26020b57cec5SDimitry Andric for (unsigned j = 0, e = OldPN->getNumOperands(); j != e; ++j) { 26030b57cec5SDimitry Andric Value *V = OldPN->getOperand(j); 26040b57cec5SDimitry Andric Value *NewV = nullptr; 26050b57cec5SDimitry Andric if (auto *C = dyn_cast<Constant>(V)) { 26060b57cec5SDimitry Andric NewV = ConstantExpr::getBitCast(C, DestTy); 26070b57cec5SDimitry Andric } else if (auto *LI = dyn_cast<LoadInst>(V)) { 2608480093f4SDimitry Andric // Explicitly perform load combine to make sure no opposing transform 2609480093f4SDimitry Andric // can remove the bitcast in the meantime and trigger an infinite loop. 2610480093f4SDimitry Andric Builder.SetInsertPoint(LI); 2611480093f4SDimitry Andric NewV = combineLoadToNewType(*LI, DestTy); 2612480093f4SDimitry Andric // Remove the old load and its use in the old phi, which itself becomes 2613480093f4SDimitry Andric // dead once the whole transform finishes. 2614fe6060f1SDimitry Andric replaceInstUsesWith(*LI, PoisonValue::get(LI->getType())); 2615480093f4SDimitry Andric eraseInstFromFunction(*LI); 26160b57cec5SDimitry Andric } else if (auto *BCI = dyn_cast<BitCastInst>(V)) { 26170b57cec5SDimitry Andric NewV = BCI->getOperand(0); 26180b57cec5SDimitry Andric } else if (auto *PrevPN = dyn_cast<PHINode>(V)) { 26190b57cec5SDimitry Andric NewV = NewPNodes[PrevPN]; 26200b57cec5SDimitry Andric } 26210b57cec5SDimitry Andric assert(NewV); 26220b57cec5SDimitry Andric NewPN->addIncoming(NewV, OldPN->getIncomingBlock(j)); 26230b57cec5SDimitry Andric } 26240b57cec5SDimitry Andric } 26250b57cec5SDimitry Andric 26260b57cec5SDimitry Andric // Traverse all accumulated PHI nodes and process its users, 26270b57cec5SDimitry Andric // which are Stores and BitcCasts. Without this processing 26280b57cec5SDimitry Andric // NewPHI nodes could be replicated and could lead to extra 26290b57cec5SDimitry Andric // moves generated after DeSSA. 26300b57cec5SDimitry Andric // If there is a store with type B, change it to type A. 26310b57cec5SDimitry Andric 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric // Replace users of BitCast B->A with NewPHI. These will help 26340b57cec5SDimitry Andric // later to get rid off a closure formed by OldPHI nodes. 26350b57cec5SDimitry Andric Instruction *RetVal = nullptr; 26360b57cec5SDimitry Andric for (auto *OldPN : OldPhiNodes) { 26370b57cec5SDimitry Andric PHINode *NewPN = NewPNodes[OldPN]; 2638e8d8bef9SDimitry Andric for (User *V : make_early_inc_range(OldPN->users())) { 26390b57cec5SDimitry Andric if (auto *SI = dyn_cast<StoreInst>(V)) { 2640480093f4SDimitry Andric assert(SI->isSimple() && SI->getOperand(0) == OldPN); 26410b57cec5SDimitry Andric Builder.SetInsertPoint(SI); 26420b57cec5SDimitry Andric auto *NewBC = 26430b57cec5SDimitry Andric cast<BitCastInst>(Builder.CreateBitCast(NewPN, SrcTy)); 26440b57cec5SDimitry Andric SI->setOperand(0, NewBC); 26455ffd83dbSDimitry Andric Worklist.push(SI); 26460b57cec5SDimitry Andric assert(hasStoreUsersOnly(*NewBC)); 26470b57cec5SDimitry Andric } 26480b57cec5SDimitry Andric else if (auto *BCI = dyn_cast<BitCastInst>(V)) { 26490b57cec5SDimitry Andric Type *TyB = BCI->getOperand(0)->getType(); 26500b57cec5SDimitry Andric Type *TyA = BCI->getType(); 2651480093f4SDimitry Andric assert(TyA == DestTy && TyB == SrcTy); 2652480093f4SDimitry Andric (void) TyA; 2653480093f4SDimitry Andric (void) TyB; 26540b57cec5SDimitry Andric Instruction *I = replaceInstUsesWith(*BCI, NewPN); 26550b57cec5SDimitry Andric if (BCI == &CI) 26560b57cec5SDimitry Andric RetVal = I; 2657480093f4SDimitry Andric } else if (auto *PHI = dyn_cast<PHINode>(V)) { 2658e8d8bef9SDimitry Andric assert(OldPhiNodes.contains(PHI)); 2659480093f4SDimitry Andric (void) PHI; 2660480093f4SDimitry Andric } else { 2661480093f4SDimitry Andric llvm_unreachable("all uses should be handled"); 26620b57cec5SDimitry Andric } 26630b57cec5SDimitry Andric } 26640b57cec5SDimitry Andric } 26650b57cec5SDimitry Andric 26660b57cec5SDimitry Andric return RetVal; 26670b57cec5SDimitry Andric } 26680b57cec5SDimitry Andric 2669fe6060f1SDimitry Andric Instruction *InstCombinerImpl::visitBitCast(BitCastInst &CI) { 2670fe6060f1SDimitry Andric // If the operands are integer typed then apply the integer transforms, 2671fe6060f1SDimitry Andric // otherwise just apply the common ones. 2672fe6060f1SDimitry Andric Value *Src = CI.getOperand(0); 2673fe6060f1SDimitry Andric Type *SrcTy = Src->getType(); 2674fe6060f1SDimitry Andric Type *DestTy = CI.getType(); 2675fe6060f1SDimitry Andric 2676fe6060f1SDimitry Andric // Get rid of casts from one type to the same type. These are useless and can 2677fe6060f1SDimitry Andric // be replaced by the operand. 2678fe6060f1SDimitry Andric if (DestTy == Src->getType()) 2679fe6060f1SDimitry Andric return replaceInstUsesWith(CI, Src); 2680fe6060f1SDimitry Andric 26815ffd83dbSDimitry Andric if (FixedVectorType *DestVTy = dyn_cast<FixedVectorType>(DestTy)) { 26825ffd83dbSDimitry Andric // Beware: messing with this target-specific oddity may cause trouble. 26835ffd83dbSDimitry Andric if (DestVTy->getNumElements() == 1 && SrcTy->isX86_MMXTy()) { 26840b57cec5SDimitry Andric Value *Elem = Builder.CreateBitCast(Src, DestVTy->getElementType()); 2685fe6060f1SDimitry Andric return InsertElementInst::Create(PoisonValue::get(DestTy), Elem, 26860b57cec5SDimitry Andric Constant::getNullValue(Type::getInt32Ty(CI.getContext()))); 26870b57cec5SDimitry Andric } 26880b57cec5SDimitry Andric 26890b57cec5SDimitry Andric if (isa<IntegerType>(SrcTy)) { 26900b57cec5SDimitry Andric // If this is a cast from an integer to vector, check to see if the input 26910b57cec5SDimitry Andric // is a trunc or zext of a bitcast from vector. If so, we can replace all 26920b57cec5SDimitry Andric // the casts with a shuffle and (potentially) a bitcast. 26930b57cec5SDimitry Andric if (isa<TruncInst>(Src) || isa<ZExtInst>(Src)) { 26940b57cec5SDimitry Andric CastInst *SrcCast = cast<CastInst>(Src); 26950b57cec5SDimitry Andric if (BitCastInst *BCIn = dyn_cast<BitCastInst>(SrcCast->getOperand(0))) 26960b57cec5SDimitry Andric if (isa<VectorType>(BCIn->getOperand(0)->getType())) 2697480093f4SDimitry Andric if (Instruction *I = optimizeVectorResizeWithIntegerBitCasts( 2698480093f4SDimitry Andric BCIn->getOperand(0), cast<VectorType>(DestTy), *this)) 26990b57cec5SDimitry Andric return I; 27000b57cec5SDimitry Andric } 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric // If the input is an 'or' instruction, we may be doing shifts and ors to 27030b57cec5SDimitry Andric // assemble the elements of the vector manually. Try to rip the code out 27040b57cec5SDimitry Andric // and replace it with insertelements. 27050b57cec5SDimitry Andric if (Value *V = optimizeIntegerToVectorInsertions(CI, *this)) 27060b57cec5SDimitry Andric return replaceInstUsesWith(CI, V); 27070b57cec5SDimitry Andric } 27080b57cec5SDimitry Andric } 27090b57cec5SDimitry Andric 27105ffd83dbSDimitry Andric if (FixedVectorType *SrcVTy = dyn_cast<FixedVectorType>(SrcTy)) { 27110b57cec5SDimitry Andric if (SrcVTy->getNumElements() == 1) { 27120b57cec5SDimitry Andric // If our destination is not a vector, then make this a straight 27130b57cec5SDimitry Andric // scalar-scalar cast. 27140b57cec5SDimitry Andric if (!DestTy->isVectorTy()) { 27150b57cec5SDimitry Andric Value *Elem = 27160b57cec5SDimitry Andric Builder.CreateExtractElement(Src, 27170b57cec5SDimitry Andric Constant::getNullValue(Type::getInt32Ty(CI.getContext()))); 27180b57cec5SDimitry Andric return CastInst::Create(Instruction::BitCast, Elem, DestTy); 27190b57cec5SDimitry Andric } 27200b57cec5SDimitry Andric 27210b57cec5SDimitry Andric // Otherwise, see if our source is an insert. If so, then use the scalar 27220b57cec5SDimitry Andric // component directly: 27230b57cec5SDimitry Andric // bitcast (inselt <1 x elt> V, X, 0) to <n x m> --> bitcast X to <n x m> 27240b57cec5SDimitry Andric if (auto *InsElt = dyn_cast<InsertElementInst>(Src)) 27250b57cec5SDimitry Andric return new BitCastInst(InsElt->getOperand(1), DestTy); 27260b57cec5SDimitry Andric } 2727349cc55cSDimitry Andric 2728349cc55cSDimitry Andric // Convert an artificial vector insert into more analyzable bitwise logic. 2729349cc55cSDimitry Andric unsigned BitWidth = DestTy->getScalarSizeInBits(); 2730349cc55cSDimitry Andric Value *X, *Y; 2731349cc55cSDimitry Andric uint64_t IndexC; 2732349cc55cSDimitry Andric if (match(Src, m_OneUse(m_InsertElt(m_OneUse(m_BitCast(m_Value(X))), 2733349cc55cSDimitry Andric m_Value(Y), m_ConstantInt(IndexC)))) && 2734349cc55cSDimitry Andric DestTy->isIntegerTy() && X->getType() == DestTy && 27354824e7fdSDimitry Andric Y->getType()->isIntegerTy() && isDesirableIntType(BitWidth)) { 2736349cc55cSDimitry Andric // Adjust for big endian - the LSBs are at the high index. 2737349cc55cSDimitry Andric if (DL.isBigEndian()) 2738349cc55cSDimitry Andric IndexC = SrcVTy->getNumElements() - 1 - IndexC; 2739349cc55cSDimitry Andric 2740349cc55cSDimitry Andric // We only handle (endian-normalized) insert to index 0. Any other insert 2741349cc55cSDimitry Andric // would require a left-shift, so that is an extra instruction. 2742349cc55cSDimitry Andric if (IndexC == 0) { 2743349cc55cSDimitry Andric // bitcast (inselt (bitcast X), Y, 0) --> or (and X, MaskC), (zext Y) 2744349cc55cSDimitry Andric unsigned EltWidth = Y->getType()->getScalarSizeInBits(); 2745349cc55cSDimitry Andric APInt MaskC = APInt::getHighBitsSet(BitWidth, BitWidth - EltWidth); 2746349cc55cSDimitry Andric Value *AndX = Builder.CreateAnd(X, MaskC); 2747349cc55cSDimitry Andric Value *ZextY = Builder.CreateZExt(Y, DestTy); 2748349cc55cSDimitry Andric return BinaryOperator::CreateOr(AndX, ZextY); 2749349cc55cSDimitry Andric } 2750349cc55cSDimitry Andric } 27510b57cec5SDimitry Andric } 27520b57cec5SDimitry Andric 27538bcb0991SDimitry Andric if (auto *Shuf = dyn_cast<ShuffleVectorInst>(Src)) { 27540b57cec5SDimitry Andric // Okay, we have (bitcast (shuffle ..)). Check to see if this is 27550b57cec5SDimitry Andric // a bitcast to a vector with the same # elts. 27568bcb0991SDimitry Andric Value *ShufOp0 = Shuf->getOperand(0); 27578bcb0991SDimitry Andric Value *ShufOp1 = Shuf->getOperand(1); 2758e8d8bef9SDimitry Andric auto ShufElts = cast<VectorType>(Shuf->getType())->getElementCount(); 2759e8d8bef9SDimitry Andric auto SrcVecElts = cast<VectorType>(ShufOp0->getType())->getElementCount(); 27608bcb0991SDimitry Andric if (Shuf->hasOneUse() && DestTy->isVectorTy() && 2761e8d8bef9SDimitry Andric cast<VectorType>(DestTy)->getElementCount() == ShufElts && 2762e8d8bef9SDimitry Andric ShufElts == SrcVecElts) { 27630b57cec5SDimitry Andric BitCastInst *Tmp; 27640b57cec5SDimitry Andric // If either of the operands is a cast from CI.getType(), then 27650b57cec5SDimitry Andric // evaluating the shuffle in the casted destination's type will allow 27660b57cec5SDimitry Andric // us to eliminate at least one cast. 27678bcb0991SDimitry Andric if (((Tmp = dyn_cast<BitCastInst>(ShufOp0)) && 27680b57cec5SDimitry Andric Tmp->getOperand(0)->getType() == DestTy) || 27698bcb0991SDimitry Andric ((Tmp = dyn_cast<BitCastInst>(ShufOp1)) && 27700b57cec5SDimitry Andric Tmp->getOperand(0)->getType() == DestTy)) { 27718bcb0991SDimitry Andric Value *LHS = Builder.CreateBitCast(ShufOp0, DestTy); 27728bcb0991SDimitry Andric Value *RHS = Builder.CreateBitCast(ShufOp1, DestTy); 27730b57cec5SDimitry Andric // Return a new shuffle vector. Use the same element ID's, as we 27740b57cec5SDimitry Andric // know the vector types match #elts. 27755ffd83dbSDimitry Andric return new ShuffleVectorInst(LHS, RHS, Shuf->getShuffleMask()); 27760b57cec5SDimitry Andric } 27770b57cec5SDimitry Andric } 27788bcb0991SDimitry Andric 2779bdd1243dSDimitry Andric // A bitcasted-to-scalar and byte/bit reversing shuffle is better recognized 2780bdd1243dSDimitry Andric // as a byte/bit swap: 2781bdd1243dSDimitry Andric // bitcast <N x i8> (shuf X, undef, <N, N-1,...0>) -> bswap (bitcast X) 2782bdd1243dSDimitry Andric // bitcast <N x i1> (shuf X, undef, <N, N-1,...0>) -> bitreverse (bitcast X) 2783bdd1243dSDimitry Andric if (DestTy->isIntegerTy() && ShufElts.getKnownMinValue() % 2 == 0 && 2784bdd1243dSDimitry Andric Shuf->hasOneUse() && Shuf->isReverse()) { 2785bdd1243dSDimitry Andric unsigned IntrinsicNum = 0; 2786bdd1243dSDimitry Andric if (DL.isLegalInteger(DestTy->getScalarSizeInBits()) && 2787bdd1243dSDimitry Andric SrcTy->getScalarSizeInBits() == 8) { 2788bdd1243dSDimitry Andric IntrinsicNum = Intrinsic::bswap; 2789bdd1243dSDimitry Andric } else if (SrcTy->getScalarSizeInBits() == 1) { 2790bdd1243dSDimitry Andric IntrinsicNum = Intrinsic::bitreverse; 2791bdd1243dSDimitry Andric } 2792bdd1243dSDimitry Andric if (IntrinsicNum != 0) { 27938bcb0991SDimitry Andric assert(ShufOp0->getType() == SrcTy && "Unexpected shuffle mask"); 2794fe6060f1SDimitry Andric assert(match(ShufOp1, m_Undef()) && "Unexpected shuffle op"); 2795bdd1243dSDimitry Andric Function *BswapOrBitreverse = 2796bdd1243dSDimitry Andric Intrinsic::getDeclaration(CI.getModule(), IntrinsicNum, DestTy); 27978bcb0991SDimitry Andric Value *ScalarX = Builder.CreateBitCast(ShufOp0, DestTy); 2798bdd1243dSDimitry Andric return CallInst::Create(BswapOrBitreverse, {ScalarX}); 2799bdd1243dSDimitry Andric } 28008bcb0991SDimitry Andric } 28010b57cec5SDimitry Andric } 28020b57cec5SDimitry Andric 28030b57cec5SDimitry Andric // Handle the A->B->A cast, and there is an intervening PHI node. 28040b57cec5SDimitry Andric if (PHINode *PN = dyn_cast<PHINode>(Src)) 28050b57cec5SDimitry Andric if (Instruction *I = optimizeBitCastFromPhi(CI, PN)) 28060b57cec5SDimitry Andric return I; 28070b57cec5SDimitry Andric 28080b57cec5SDimitry Andric if (Instruction *I = canonicalizeBitCastExtElt(CI, *this)) 28090b57cec5SDimitry Andric return I; 28100b57cec5SDimitry Andric 28110b57cec5SDimitry Andric if (Instruction *I = foldBitCastBitwiseLogic(CI, Builder)) 28120b57cec5SDimitry Andric return I; 28130b57cec5SDimitry Andric 28140b57cec5SDimitry Andric if (Instruction *I = foldBitCastSelect(CI, Builder)) 28150b57cec5SDimitry Andric return I; 28160b57cec5SDimitry Andric 28170b57cec5SDimitry Andric return commonCastTransforms(CI); 28180b57cec5SDimitry Andric } 28190b57cec5SDimitry Andric 2820e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitAddrSpaceCast(AddrSpaceCastInst &CI) { 28215f757f3fSDimitry Andric return commonCastTransforms(CI); 28220b57cec5SDimitry Andric } 2823