mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[InstCombine] allow non-splat folds of select cond (ext X), C
llvm-svn: 282906
This commit is contained in:
parent
9a6d19a0c6
commit
6f740e7b76
@ -590,8 +590,7 @@ private:
|
||||
Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, const APInt *C);
|
||||
|
||||
// Helpers of visitSelectInst().
|
||||
Instruction *foldSelectExtConst(SelectInst &Sel, Instruction *ExtInst,
|
||||
const APInt &C);
|
||||
Instruction *foldSelectExtConst(SelectInst &Sel);
|
||||
Instruction *foldSelectOpOp(SelectInst &SI, Instruction *TI, Instruction *FI);
|
||||
Instruction *foldSelectIntoOp(SelectInst &SI, Value *, Value *);
|
||||
Instruction *foldSPFofSPF(Instruction *Inner, SelectPatternFlavor SPF1,
|
||||
|
@ -916,32 +916,42 @@ static Instruction *foldAddSubSelect(SelectInst &SI,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If one of the operands is a sext/zext from i1 and the other is a constant,
|
||||
/// we may be able to create an i1 select which can be further folded to
|
||||
/// logical ops.
|
||||
Instruction *InstCombiner::foldSelectExtConst(SelectInst &Sel,
|
||||
Instruction *ExtInst,
|
||||
const APInt &C) {
|
||||
Instruction *InstCombiner::foldSelectExtConst(SelectInst &Sel) {
|
||||
Instruction *ExtInst;
|
||||
if (!match(Sel.getTrueValue(), m_Instruction(ExtInst)) &&
|
||||
!match(Sel.getFalseValue(), m_Instruction(ExtInst)))
|
||||
return nullptr;
|
||||
|
||||
auto ExtOpcode = ExtInst->getOpcode();
|
||||
if (ExtOpcode != Instruction::ZExt && ExtOpcode != Instruction::SExt)
|
||||
return nullptr;
|
||||
|
||||
// TODO: Handle larger types? That requires adjusting FoldOpIntoSelect too.
|
||||
Value *SmallVal = ExtInst->getOperand(0);
|
||||
Type *SmallType = SmallVal->getType();
|
||||
Value *X = ExtInst->getOperand(0);
|
||||
Type *SmallType = X->getType();
|
||||
if (!SmallType->getScalarType()->isIntegerTy(1))
|
||||
return nullptr;
|
||||
|
||||
Value *Cond = Sel.getCondition();
|
||||
bool IsExtTrueVal = Sel.getTrueValue() == ExtInst;
|
||||
bool IsSext = ExtInst->getOpcode() == Instruction::SExt;
|
||||
if (C == 0 || (!IsSext && C == 1) || (IsSext && C.isAllOnesValue())) {
|
||||
Value *SmallConst = ConstantInt::get(SmallType, C.trunc(1));
|
||||
Value *TrueVal = IsExtTrueVal ? SmallVal : SmallConst;
|
||||
Value *FalseVal = IsExtTrueVal ? SmallConst : SmallVal;
|
||||
Value *NewSel = Builder->CreateSelect(Cond, TrueVal, FalseVal,
|
||||
"fold." + Sel.getName(), &Sel);
|
||||
Constant *C;
|
||||
if (!match(Sel.getTrueValue(), m_Constant(C)) &&
|
||||
!match(Sel.getFalseValue(), m_Constant(C)))
|
||||
return nullptr;
|
||||
|
||||
if (IsSext)
|
||||
return new SExtInst(NewSel, Sel.getType());
|
||||
// If the constant is the same after truncation to the smaller type and
|
||||
// extension to the original type, we can narrow the select.
|
||||
Type *SelType = Sel.getType();
|
||||
Constant *TruncC = ConstantExpr::getTrunc(C, SmallType);
|
||||
Constant *ExtC = ConstantExpr::getCast(ExtOpcode, TruncC, SelType);
|
||||
if (ExtC == C) {
|
||||
Value *Cond = Sel.getCondition();
|
||||
Value *TruncCVal = cast<Value>(TruncC);
|
||||
if (ExtInst == Sel.getFalseValue())
|
||||
std::swap(X, TruncCVal);
|
||||
|
||||
return new ZExtInst(NewSel, Sel.getType());
|
||||
// select Cond, (ext X), C --> ext(select Cond, X, C')
|
||||
// select Cond, C, (ext X) --> ext(select Cond, C', X)
|
||||
Value *NewSel = Builder->CreateSelect(Cond, X, TruncCVal, "narrow", &Sel);
|
||||
return CastInst::Create(Instruction::CastOps(ExtOpcode), NewSel, SelType);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -1172,23 +1182,8 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||
if (Instruction *IV = foldSelectOpOp(SI, TI, FI))
|
||||
return IV;
|
||||
|
||||
// (select C, (ext X), const) -> (ext (select C, X, const')) and variations
|
||||
// thereof when extending from i1, as that allows further folding into logic
|
||||
// ops. When the sext is from a larger type, prefer to have it as an operand.
|
||||
if (TI && (TI->getOpcode() == Instruction::ZExt ||
|
||||
TI->getOpcode() == Instruction::SExt)) {
|
||||
const APInt *C;
|
||||
if (match(FalseVal, m_APInt(C)))
|
||||
if (auto *I = foldSelectExtConst(SI, TI, *C))
|
||||
return I;
|
||||
}
|
||||
if (FI && (FI->getOpcode() == Instruction::ZExt ||
|
||||
FI->getOpcode() == Instruction::SExt)) {
|
||||
const APInt *C;
|
||||
if (match(TrueVal, m_APInt(C)))
|
||||
if (auto *I = foldSelectExtConst(SI, FI, *C))
|
||||
return I;
|
||||
}
|
||||
if (Instruction *I = foldSelectExtConst(SI))
|
||||
return I;
|
||||
|
||||
// See if we can fold the select into one of our operands.
|
||||
if (SelType->isIntOrIntVectorTy() || SelType->isFPOrFPVectorTy()) {
|
||||
|
@ -168,8 +168,8 @@ define <2 x i32> @test_vectors_sext(<2 x i1> %cca, <2 x i1> %ccb) {
|
||||
|
||||
define <2 x i32> @test_vectors_sext_nonsplat(<2 x i1> %cca, <2 x i1> %ccb) {
|
||||
; CHECK-LABEL: @test_vectors_sext_nonsplat(
|
||||
; CHECK-NEXT: [[CCAX:%.*]] = sext <2 x i1> %cca to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> %ccb, <2 x i32> [[CCAX]], <2 x i32> <i32 0, i32 -1>
|
||||
; CHECK-NEXT: [[NARROW:%.*]] = select <2 x i1> %ccb, <2 x i1> %cca, <2 x i1> <i1 false, i1 true>
|
||||
; CHECK-NEXT: [[R:%.*]] = sext <2 x i1> [[NARROW]] to <2 x i32>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%ccax = sext <2 x i1> %cca to <2 x i32>
|
||||
@ -190,8 +190,8 @@ define <2 x i32> @test_vectors_zext(<2 x i1> %cca, <2 x i1> %ccb) {
|
||||
|
||||
define <2 x i32> @test_vectors_zext_nonsplat(<2 x i1> %cca, <2 x i1> %ccb) {
|
||||
; CHECK-LABEL: @test_vectors_zext_nonsplat(
|
||||
; CHECK-NEXT: [[CCAX:%.*]] = zext <2 x i1> %cca to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> %ccb, <2 x i32> [[CCAX]], <2 x i32> <i32 1, i32 0>
|
||||
; CHECK-NEXT: [[NARROW:%.*]] = select <2 x i1> %ccb, <2 x i1> %cca, <2 x i1> <i1 true, i1 false>
|
||||
; CHECK-NEXT: [[R:%.*]] = zext <2 x i1> [[NARROW]] to <2 x i32>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%ccax = zext <2 x i1> %cca to <2 x i32>
|
||||
|
Loading…
Reference in New Issue
Block a user