llvm.org GIT mirror llvm / 5933b24
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317592 91177308-0d34-0410-b5e6-96231b3b80d8 Krzysztof Parzyszek 1 year, 11 months ago
1 changed file(s) with 52 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
160160 };
161161
162162 struct Simplifier {
163 using Rule = std::function;
164
165 void addRule(const Rule &R) { Rules.push_back(R); }
163 struct Rule {
164 using FuncType = std::function;
165 Rule(StringRef N, FuncType F) : Name(N), Fn(F) {}
166 StringRef Name; // For debugging.
167 FuncType Fn;
168 };
169
170 void addRule(StringRef N, const Rule::FuncType &F) {
171 Rules.push_back(Rule(N, F));
172 }
166173
167174 private:
168175 struct WorkListType {
521528 continue;
522529 bool Changed = false;
523530 for (Rule &R : Rules) {
524 Value *W = R(U, C.Ctx);
531 Value *W = R.Fn(U, C.Ctx);
525532 if (!W)
526533 continue;
527534 Changed = true;
15431550 return R;
15441551 }
15451552
1553 static bool hasZeroSignBit(const Value *V) {
1554 if (const auto *CI = dyn_cast(V))
1555 return (CI->getType()->getSignBit() & CI->getSExtValue()) == 0;
1556 const Instruction *I = dyn_cast(V);
1557 if (!I)
1558 return false;
1559 switch (I->getOpcode()) {
1560 case Instruction::LShr:
1561 if (const auto SI = dyn_cast(I->getOperand(1)))
1562 return SI->getZExtValue() > 0;
1563 return false;
1564 case Instruction::Or:
1565 case Instruction::Xor:
1566 return hasZeroSignBit(I->getOperand(0)) &&
1567 hasZeroSignBit(I->getOperand(1));
1568 case Instruction::And:
1569 return hasZeroSignBit(I->getOperand(0)) ||
1570 hasZeroSignBit(I->getOperand(1));
1571 }
1572 return false;
1573 }
1574
15461575 void PolynomialMultiplyRecognize::setupSimplifier() {
1547 Simp.addRule(
1576 Simp.addRule("sink-zext",
15481577 // Sink zext past bitwise operations.
15491578 [](Instruction *I, LLVMContext &Ctx) -> Value* {
15501579 if (I->getOpcode() != Instruction::ZExt)
15651594 B.CreateZExt(T->getOperand(0), I->getType()),
15661595 B.CreateZExt(T->getOperand(1), I->getType()));
15671596 });
1568 Simp.addRule(
1597 Simp.addRule("xor/and -> and/xor",
15691598 // (xor (and x a) (and y a)) -> (and (xor x y) a)
15701599 [](Instruction *I, LLVMContext &Ctx) -> Value* {
15711600 if (I->getOpcode() != Instruction::Xor)
15831612 return B.CreateAnd(B.CreateXor(And0->getOperand(0), And1->getOperand(0)),
15841613 And0->getOperand(1));
15851614 });
1586 Simp.addRule(
1615 Simp.addRule("sink binop into select",
15871616 // (Op (select c x y) z) -> (select c (Op x z) (Op y z))
15881617 // (Op x (select c y z)) -> (select c (Op x y) (Op x z))
15891618 [](Instruction *I, LLVMContext &Ctx) -> Value* {
16091638 }
16101639 return nullptr;
16111640 });
1612 Simp.addRule(
1641 Simp.addRule("fold select-select",
16131642 // (select c (select c x y) z) -> (select c x z)
16141643 // (select c x (select c y z)) -> (select c x z)
16151644 [](Instruction *I, LLVMContext &Ctx) -> Value* {
16281657 }
16291658 return nullptr;
16301659 });
1631 Simp.addRule(
1660 Simp.addRule("or-signbit -> xor-signbit",
16321661 // (or (lshr x 1) 0x800.0) -> (xor (lshr x 1) 0x800.0)
16331662 [](Instruction *I, LLVMContext &Ctx) -> Value* {
16341663 if (I->getOpcode() != Instruction::Or)
16351664 return nullptr;
1636 Instruction *LShr = dyn_cast(I->getOperand(0));
1637 if (!LShr || LShr->getOpcode() != Instruction::LShr)
1638 return nullptr;
1639 ConstantInt *One = dyn_cast(LShr->getOperand(1));
1640 if (!One || One->getZExtValue() != 1)
1641 return nullptr;
16421665 ConstantInt *Msb = dyn_cast(I->getOperand(1));
16431666 if (!Msb || Msb->getZExtValue() != Msb->getType()->getSignBit())
16441667 return nullptr;
1645 return IRBuilder<>(Ctx).CreateXor(LShr, Msb);
1668 if (!hasZeroSignBit(I->getOperand(0)))
1669 return nullptr;
1670 return IRBuilder<>(Ctx).CreateXor(I->getOperand(0), Msb);
16461671 });
1647 Simp.addRule(
1672 Simp.addRule("sink lshr into binop",
16481673 // (lshr (BitOp x y) c) -> (BitOp (lshr x c) (lshr y c))
16491674 [](Instruction *I, LLVMContext &Ctx) -> Value* {
16501675 if (I->getOpcode() != Instruction::LShr)
16661691 B.CreateLShr(BitOp->getOperand(0), S),
16671692 B.CreateLShr(BitOp->getOperand(1), S));
16681693 });
1669 Simp.addRule(
1694 Simp.addRule("expose bitop-const",
16701695 // (BitOp1 (BitOp2 x a) b) -> (BitOp2 x (BitOp1 a b))
16711696 [](Instruction *I, LLVMContext &Ctx) -> Value* {
16721697 auto IsBitOp = [](unsigned Op) -> bool {
17361761 // XXX: Currently this approach can modify the loop before being 100% sure
17371762 // that the transformation can be carried out.
17381763 bool FoundPreScan = false;
1764 auto FeedsPHI = [LoopB](const Value *V) -> bool {
1765 for (const Value *U : V->users()) {
1766 if (const auto *P = dyn_cast(U))
1767 if (P->getParent() == LoopB)
1768 return true;
1769 }
1770 return false;
1771 };
17391772 for (Instruction &In : *LoopB) {
17401773 SelectInst *SI = dyn_cast(&In);
1741 if (!SI)
1774 if (!SI || !FeedsPHI(SI))
17421775 continue;
17431776
17441777 Simplifier::Context C(SI);