[llvm] r282906 - [InstCombine] allow non-splat folds of select cond (ext X), C

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 30 12:49:23 PDT 2016


Author: spatel
Date: Fri Sep 30 14:49:22 2016
New Revision: 282906

URL: http://llvm.org/viewvc/llvm-project?rev=282906&view=rev
Log:
[InstCombine] allow non-splat folds of select cond (ext X), C

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/trunk/test/Transforms/InstCombine/select-bitext.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=282906&r1=282905&r2=282906&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h Fri Sep 30 14:49:22 2016
@@ -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,

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=282906&r1=282905&r2=282906&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Fri Sep 30 14:49:22 2016
@@ -916,32 +916,42 @@ static Instruction *foldAddSubSelect(Sel
   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);
-
-    if (IsSext)
-      return new SExtInst(NewSel, Sel.getType());
+  Constant *C;
+  if (!match(Sel.getTrueValue(), m_Constant(C)) &&
+      !match(Sel.getFalseValue(), m_Constant(C)))
+    return nullptr;
 
-    return new ZExtInst(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);
+
+    // 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::visitSelectIn
     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()) {

Modified: llvm/trunk/test/Transforms/InstCombine/select-bitext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/select-bitext.ll?rev=282906&r1=282905&r2=282906&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/select-bitext.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/select-bitext.ll Fri Sep 30 14:49:22 2016
@@ -168,8 +168,8 @@ define <2 x i32> @test_vectors_sext(<2 x
 
 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
 
 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>




More information about the llvm-commits mailing list