//===- InstCombineSelect.cpp ----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the visitSelect function.
//
//===----------------------------------------------------------------------===//
#include "InstCombine.h"
#include "llvm/Support/PatternMatch.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
using namespace llvm;
using namespace PatternMatch;
/// MatchSelectPattern - Pattern match integer [SU]MIN, [SU]MAX, and ABS idioms,
/// returning the kind and providing the out parameter results if we
/// successfully match.
static SelectPatternFlavor
MatchSelectPattern(Value *V, Value *&LHS, Value *&RHS) {
SelectInst *SI = dyn_cast<SelectInst>(V);
if (SI == 0) return SPF_UNKNOWN;
ICmpInst *ICI = dyn_cast<ICmpInst>(SI->getCondition());
if (ICI == 0) return SPF_UNKNOWN;
LHS = ICI->getOperand(0);
RHS = ICI->getOperand(1);
// (icmp X, Y) ? X : Y
if (SI->getTrueValue() == ICI->getOperand(0) &&
SI->getFalseValue() == ICI->getOperand(1)) {
switch (ICI->getPredicate()) {
default: return SPF_UNKNOWN; // Equality.
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE: return SPF_UMAX;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE: return SPF_SMAX;
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE: return SPF_UMIN;
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE: return SPF_SMIN;
}
}
// (icmp X, Y) ? Y : X
if (SI->getTrueValue() == ICI->getOperand(1) &&
SI->getFalseValue() == ICI->getOperand(0)) {
switch (ICI->getPredicate()) {
default: return SPF_UNKNOWN; // Equality.
case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE: return SPF_UMIN;
case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE: return SPF_SMIN;
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE: return SPF_UMAX;
case ICmpInst::ICMP_SLT:
case ICmpInst::ICMP_SLE: return SPF_SMAX;
}
}
// TODO: (X > 4) ? X : 5 --> (X >= 5) ? X : 5 --> MAX(X, 5)
return SPF_UNKNOWN;
}
/// GetSelectFoldableOperands - We want to turn code that looks like this:
/// %C = or %A, %B
/// %D = select %cond, %C, %A
/// into:
/// %C = select %cond, %B, 0
/// %D = or %A, %C
///
/// Assuming that the specified instruction is an operand to the select, return
/// a bitmask indicating which operands of this instruction are foldable if they
/// equal the other incoming value of the select.
///
static unsigned GetSelectFoldableOperands(Instruction *I) {
switch (I->getOpcode()) {
case Instruction::Add:
case Instruction::Mul:
case Instruction::And:
case Instruction::Or:
case Instruction::Xor:
return 3; // Can fold through either operand.
case Instruction::Sub: // Can only fold on the amount subtracted.
case Instruction::Shl: // Can only fold on the shift amount.
case Instruction::LShr:
case Instruction::AShr:
return 1;
default:
return 0; // Cannot fold
}
}
/// GetSelectFoldableConstant - For the same transformation as the previous
/// function, return the identity constant that goes into the select.
static Constant *GetSelectFoldableConstant(Instruction *I) {
switch (I->getOpcode()) {
default: llvm_unreachable("This cannot happen!");
case Instruction::Add:
case Instruction::Sub:
case Instruction::Or:
case Instruction::Xor:
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
return Constant::getNullValue(I->getType());
case Instruction::And:
return Constant::getAllOnesValue(I->getType());
case Instruction::Mul:
return ConstantInt::get(I->getType(), 1);
}
}
/// FoldSelectOpOp - Here we have (select c, TI, FI), and we know that TI and FI
/// have the same opcode and only one use each. Try to simplify this.
Instruction *InstCombiner::FoldSelectOpOp(SelectInst &SI, Instruction *TI,
Instruction *FI) {
if (TI->getNumOperands() == 1) {
// If this is a non-volatile load or a cast from the same type,
// merge.
if (TI->isCast()) {
if (TI->getOperand(0)->getType() != FI->getOperand(0)->getType())
return 0;
// The select condition may be a vector. We may only change the operand
// type if the vector width remains the same (and matches the condition).
Type *CondTy = SI.getCondition