[llvm] r317592 - [Hexagon] Make a test more flexible in HexagonLoopIdiomRecognition

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 7 09:05:54 PST 2017


Author: kparzysz
Date: Tue Nov  7 09:05:54 2017
New Revision: 317592

URL: http://llvm.org/viewvc/llvm-project?rev=317592&view=rev
Log:
[Hexagon] Make a test more flexible in HexagonLoopIdiomRecognition

An "or" that sets the sign-bit can be replaced with a "xor", if
the sign-bit was known to be clear before. With some changes to
instruction combining, the simple sign-bit check was failing.
Replace it with a more flexible one to catch more cases.

Modified:
    llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp

Modified: llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp?rev=317592&r1=317591&r2=317592&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp Tue Nov  7 09:05:54 2017
@@ -161,9 +161,16 @@ namespace {
   };
 
   struct Simplifier {
-    using Rule = std::function<Value * (Instruction *, LLVMContext &)>;
+    struct Rule {
+      using FuncType = std::function<Value* (Instruction*, LLVMContext&)>;
+      Rule(StringRef N, FuncType F) : Name(N), Fn(F) {}
+      StringRef Name;   // For debugging.
+      FuncType Fn;
+    };
 
-    void addRule(const Rule &R) { Rules.push_back(R); }
+    void addRule(StringRef N, const Rule::FuncType &F) {
+      Rules.push_back(Rule(N, F));
+    }
 
   private:
     struct WorkListType {
@@ -522,7 +529,7 @@ Value *Simplifier::simplify(Context &C)
       continue;
     bool Changed = false;
     for (Rule &R : Rules) {
-      Value *W = R(U, C.Ctx);
+      Value *W = R.Fn(U, C.Ctx);
       if (!W)
         continue;
       Changed = true;
@@ -1544,8 +1551,30 @@ Value *PolynomialMultiplyRecognize::gene
   return R;
 }
 
+static bool hasZeroSignBit(const Value *V) {
+  if (const auto *CI = dyn_cast<const ConstantInt>(V))
+    return (CI->getType()->getSignBit() & CI->getSExtValue()) == 0;
+  const Instruction *I = dyn_cast<const Instruction>(V);
+  if (!I)
+    return false;
+  switch (I->getOpcode()) {
+    case Instruction::LShr:
+      if (const auto SI = dyn_cast<const ConstantInt>(I->getOperand(1)))
+        return SI->getZExtValue() > 0;
+      return false;
+    case Instruction::Or:
+    case Instruction::Xor:
+      return hasZeroSignBit(I->getOperand(0)) &&
+             hasZeroSignBit(I->getOperand(1));
+    case Instruction::And:
+      return hasZeroSignBit(I->getOperand(0)) ||
+             hasZeroSignBit(I->getOperand(1));
+  }
+  return false;
+}
+
 void PolynomialMultiplyRecognize::setupSimplifier() {
-  Simp.addRule(
+  Simp.addRule("sink-zext",
     // Sink zext past bitwise operations.
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
       if (I->getOpcode() != Instruction::ZExt)
@@ -1566,7 +1595,7 @@ void PolynomialMultiplyRecognize::setupS
                            B.CreateZExt(T->getOperand(0), I->getType()),
                            B.CreateZExt(T->getOperand(1), I->getType()));
     });
-  Simp.addRule(
+  Simp.addRule("xor/and -> and/xor",
     // (xor (and x a) (and y a)) -> (and (xor x y) a)
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
       if (I->getOpcode() != Instruction::Xor)
@@ -1584,7 +1613,7 @@ void PolynomialMultiplyRecognize::setupS
       return B.CreateAnd(B.CreateXor(And0->getOperand(0), And1->getOperand(0)),
                          And0->getOperand(1));
     });
-  Simp.addRule(
+  Simp.addRule("sink binop into select",
     // (Op (select c x y) z) -> (select c (Op x z) (Op y z))
     // (Op x (select c y z)) -> (select c (Op x y) (Op x z))
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
@@ -1610,7 +1639,7 @@ void PolynomialMultiplyRecognize::setupS
       }
       return nullptr;
     });
-  Simp.addRule(
+  Simp.addRule("fold select-select",
     // (select c (select c x y) z) -> (select c x z)
     // (select c x (select c y z)) -> (select c x z)
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
@@ -1629,23 +1658,19 @@ void PolynomialMultiplyRecognize::setupS
       }
       return nullptr;
     });
-  Simp.addRule(
+  Simp.addRule("or-signbit -> xor-signbit",
     // (or (lshr x 1) 0x800.0) -> (xor (lshr x 1) 0x800.0)
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
       if (I->getOpcode() != Instruction::Or)
         return nullptr;
-      Instruction *LShr = dyn_cast<Instruction>(I->getOperand(0));
-      if (!LShr || LShr->getOpcode() != Instruction::LShr)
-        return nullptr;
-      ConstantInt *One = dyn_cast<ConstantInt>(LShr->getOperand(1));
-      if (!One || One->getZExtValue() != 1)
-        return nullptr;
       ConstantInt *Msb = dyn_cast<ConstantInt>(I->getOperand(1));
       if (!Msb || Msb->getZExtValue() != Msb->getType()->getSignBit())
         return nullptr;
-      return IRBuilder<>(Ctx).CreateXor(LShr, Msb);
+      if (!hasZeroSignBit(I->getOperand(0)))
+        return nullptr;
+      return IRBuilder<>(Ctx).CreateXor(I->getOperand(0), Msb);
     });
-  Simp.addRule(
+  Simp.addRule("sink lshr into binop",
     // (lshr (BitOp x y) c) -> (BitOp (lshr x c) (lshr y c))
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
       if (I->getOpcode() != Instruction::LShr)
@@ -1667,7 +1692,7 @@ void PolynomialMultiplyRecognize::setupS
                 B.CreateLShr(BitOp->getOperand(0), S),
                 B.CreateLShr(BitOp->getOperand(1), S));
     });
-  Simp.addRule(
+  Simp.addRule("expose bitop-const",
     // (BitOp1 (BitOp2 x a) b) -> (BitOp2 x (BitOp1 a b))
     [](Instruction *I, LLVMContext &Ctx) -> Value* {
       auto IsBitOp = [](unsigned Op) -> bool {
@@ -1737,9 +1762,17 @@ bool PolynomialMultiplyRecognize::recogn
   // XXX: Currently this approach can modify the loop before being 100% sure
   // that the transformation can be carried out.
   bool FoundPreScan = false;
+  auto FeedsPHI = [LoopB](const Value *V) -> bool {
+    for (const Value *U : V->users()) {
+      if (const auto *P = dyn_cast<const PHINode>(U))
+        if (P->getParent() == LoopB)
+          return true;
+    }
+    return false;
+  };
   for (Instruction &In : *LoopB) {
     SelectInst *SI = dyn_cast<SelectInst>(&In);
-    if (!SI)
+    if (!SI || !FeedsPHI(SI))
       continue;
 
     Simplifier::Context C(SI);




More information about the llvm-commits mailing list