[llvm] r336558 - [InstCombine] generalize safe vector constant utility

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 9 09:16:51 PDT 2018


Author: spatel
Date: Mon Jul  9 09:16:51 2018
New Revision: 336558

URL: http://llvm.org/viewvc/llvm-project?rev=336558&view=rev
Log:
[InstCombine] generalize safe vector constant utility

This is almost NFC, but there could be some case where the original
code had undefs in the constants (rather than just the shuffle mask),
and we'll use safe constants rather than undefs now.

The FIXME noted in foldShuffledBinop() is already visible in existing
tests, so correcting that is the next step.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=336558&r1=336557&r2=336558&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h Mon Jul  9 09:16:51 2018
@@ -212,19 +212,26 @@ IntrinsicIDToOverflowCheckFlavor(unsigne
   }
 }
 
-/// Integer division/remainder require special handling to avoid undefined
+/// Some binary operators require special handling to avoid poison and undefined
 /// behavior. If a constant vector has undef elements, replace those undefs with
-/// '1' because that's always safe to execute.
-static inline Constant *getSafeVectorConstantForIntDivRem(Constant *In) {
-  assert(In->getType()->isVectorTy() && "Not expecting scalars here");
-  assert(In->getType()->getVectorElementType()->isIntegerTy() &&
-         "Not expecting FP opcodes/operands/constants here");
+/// identity constants because those are always safe to execute. If no identity
+/// constant exists, replace undef with '1' or '1.0'.
+static inline Constant *getSafeVectorConstantForBinop(
+      BinaryOperator::BinaryOps Opcode, Constant *In) {
+  Type *Ty = In->getType();
+  assert(Ty->isVectorTy() && "Not expecting scalars here");
 
-  unsigned NumElts = In->getType()->getVectorNumElements();
+  Type *EltTy = Ty->getVectorElementType();
+  Constant *IdentityC = ConstantExpr::getBinOpIdentity(Opcode, EltTy, true);
+  if (!IdentityC)
+    IdentityC = EltTy->isIntegerTy() ? ConstantInt::get(EltTy, 1):
+                                       ConstantFP::get(EltTy, 1.0);
+
+  unsigned NumElts = Ty->getVectorNumElements();
   SmallVector<Constant *, 16> Out(NumElts);
   for (unsigned i = 0; i != NumElts; ++i) {
     Constant *C = In->getAggregateElement(i);
-    Out[i] = isa<UndefValue>(C) ? ConstantInt::get(C->getType(), 1) : C;
+    Out[i] = isa<UndefValue>(C) ? IdentityC : C;
   }
   return ConstantVector::get(Out);
 }

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp?rev=336558&r1=336557&r2=336558&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp Mon Jul  9 09:16:51 2018
@@ -1288,33 +1288,18 @@ static Instruction *foldSelectShuffle(Sh
       Mask->containsUndefElement() &&
       (Instruction::isIntDivRem(BOpc) || Instruction::isShift(BOpc));
 
-  Constant *NewC;
+  // Select the constant elements needed for the single binop.
+  Constant *NewC = ConstantExpr::getShuffleVector(C0, C1, Mask);
   Value *V;
   if (X == Y) {
-    NewC = ConstantExpr::getShuffleVector(C0, C1, Mask);
-
     // The new binop constant must not have any potential for extra poison/UB.
     if (MightCreatePoisonOrUB) {
       // TODO: Use getBinOpAbsorber for LHS replacement constants?
       if (!ConstantsAreOp1)
         return nullptr;
 
-      Type *EltTy = Shuf.getType()->getVectorElementType();
-      auto *IdC = ConstantExpr::getBinOpIdentity(BOpc, EltTy, true);
-      if (!IdC)
-        return nullptr;
-
-      // Replace undef elements caused by the mask with identity constants.
-      NewC = ConstantExpr::getShuffleVector(C0, C1, Mask);
-      unsigned NumElts = Shuf.getType()->getVectorNumElements();
-      SmallVector<Constant *, 16> VectorOfNewC(NumElts);
-      for (unsigned i = 0; i != NumElts; i++) {
-        if (isa<UndefValue>(Mask->getAggregateElement(i)))
-          VectorOfNewC[i] = IdC;
-        else
-          VectorOfNewC[i] = NewC->getAggregateElement(i);
-      }
-      NewC = ConstantVector::get(VectorOfNewC);
+      // Replace undef elements with identity constants.
+      NewC = getSafeVectorConstantForBinop(BOpc, NewC);
     }
 
     // Remove a binop and the shuffle by rearranging the constant:
@@ -1340,7 +1325,6 @@ static Instruction *foldSelectShuffle(Sh
     // Select the variable vectors first, then perform the binop:
     // shuffle (op X, C0), (op Y, C1), M --> op (shuffle X, Y, M), C'
     // shuffle (op C0, X), (op C1, Y), M --> op C', (shuffle X, Y, M)
-    NewC = ConstantExpr::getShuffleVector(C0, C1, Mask);
     V = Builder.CreateShuffleVector(X, Y, Mask);
   }
 

Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=336558&r1=336557&r2=336558&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Mon Jul  9 09:16:51 2018
@@ -1423,8 +1423,10 @@ Instruction *InstCombiner::foldShuffledB
       // All other binop opcodes are always safe to speculate, and therefore, it
       // is fine to include undef elements for unused lanes (and using undefs
       // may help optimization).
+      // FIXME: This transform is also not poison-safe. Eg, shift-by-undef would
+      // create poison that may not exist in the original code.
       if (Inst.isIntDivRem())
-        NewC = getSafeVectorConstantForIntDivRem(NewC);
+        NewC = getSafeVectorConstantForBinop(Inst.getOpcode(), NewC);
       
       // Op(shuffle(V1, Mask), C) -> shuffle(Op(V1, NewC), Mask)
       // Op(C, shuffle(V1, Mask)) -> shuffle(Op(NewC, V1), Mask)




More information about the llvm-commits mailing list