diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:39 +0300 |
commit | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (patch) | |
tree | 64175d5cadab313b3e7039ebaa06c5bc3295e274 /contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp | |
parent | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (diff) | |
download | ydb-e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp | 206 |
1 files changed, 103 insertions, 103 deletions
diff --git a/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp b/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp index d5c83dd0ba..7718c8b0ee 100644 --- a/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp +++ b/contrib/libs/llvm12/lib/Transforms/InstCombine/InstCombineNegator.cpp @@ -42,9 +42,9 @@ #include "llvm/Support/DebugCounter.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/InstCombine/InstCombiner.h" -#include <cassert> -#include <cstdint> +#include "llvm/Transforms/InstCombine/InstCombiner.h" +#include <cassert> +#include <cstdint> #include <functional> #include <tuple> #include <type_traits> @@ -115,19 +115,19 @@ Negator::~Negator() { } #endif -// Due to the InstCombine's worklist management, there are no guarantees that -// each instruction we'll encounter has been visited by InstCombine already. -// In particular, most importantly for us, that means we have to canonicalize -// constants to RHS ourselves, since that is helpful sometimes. -std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) { - assert(I->getNumOperands() == 2 && "Only for binops!"); - std::array<Value *, 2> Ops{I->getOperand(0), I->getOperand(1)}; - if (I->isCommutative() && InstCombiner::getComplexity(I->getOperand(0)) < - InstCombiner::getComplexity(I->getOperand(1))) - std::swap(Ops[0], Ops[1]); - return Ops; -} - +// Due to the InstCombine's worklist management, there are no guarantees that +// each instruction we'll encounter has been visited by InstCombine already. +// In particular, most importantly for us, that means we have to canonicalize +// constants to RHS ourselves, since that is helpful sometimes. +std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) { + assert(I->getNumOperands() == 2 && "Only for binops!"); + std::array<Value *, 2> Ops{I->getOperand(0), I->getOperand(1)}; + if (I->isCommutative() && InstCombiner::getComplexity(I->getOperand(0)) < + InstCombiner::getComplexity(I->getOperand(1))) + std::swap(Ops[0], Ops[1]); + return Ops; +} + // FIXME: can this be reworked into a worklist-based algorithm while preserving // the depth-first, early bailout traversal? LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { @@ -172,13 +172,13 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { // In some cases we can give the answer without further recursion. switch (I->getOpcode()) { - case Instruction::Add: { - std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); + case Instruction::Add: { + std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); // `inc` is always negatible. - if (match(Ops[1], m_One())) - return Builder.CreateNot(Ops[0], I->getName() + ".neg"); + if (match(Ops[1], m_One())) + return Builder.CreateNot(Ops[0], I->getName() + ".neg"); break; - } + } case Instruction::Xor: // `not` is always negatible. if (match(I, m_Not(m_Value(X)))) @@ -199,10 +199,10 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { } return BO; } - // While we could negate exact arithmetic shift: - // ashr exact %x, C --> sdiv exact i8 %x, -1<<C - // iff C != 0 and C u< bitwidth(%x), we don't want to, - // because division is *THAT* much worse than a shift. + // While we could negate exact arithmetic shift: + // ashr exact %x, C --> sdiv exact i8 %x, -1<<C + // iff C != 0 and C u< bitwidth(%x), we don't want to, + // because division is *THAT* much worse than a shift. break; } case Instruction::SExt: @@ -219,15 +219,15 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { break; // Other instructions require recursive reasoning. } - if (I->getOpcode() == Instruction::Sub && - (I->hasOneUse() || match(I->getOperand(0), m_ImmConstant()))) { - // `sub` is always negatible. - // However, only do this either if the old `sub` doesn't stick around, or - // it was subtracting from a constant. Otherwise, this isn't profitable. - return Builder.CreateSub(I->getOperand(1), I->getOperand(0), - I->getName() + ".neg"); - } - + if (I->getOpcode() == Instruction::Sub && + (I->hasOneUse() || match(I->getOperand(0), m_ImmConstant()))) { + // `sub` is always negatible. + // However, only do this either if the old `sub` doesn't stick around, or + // it was subtracting from a constant. Otherwise, this isn't profitable. + return Builder.CreateSub(I->getOperand(1), I->getOperand(0), + I->getName() + ".neg"); + } + // Some other cases, while still don't require recursion, // are restricted to the one-use case. if (!V->hasOneUse()) @@ -239,8 +239,8 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { // While this is normally not behind a use-check, // let's consider division to be special since it's costly. if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) { - if (!Op1C->containsUndefOrPoisonElement() && - Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) { + if (!Op1C->containsUndefOrPoisonElement() && + Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) { Value *BO = Builder.CreateSDiv(I->getOperand(0), ConstantExpr::getNeg(Op1C), I->getName() + ".neg"); @@ -261,13 +261,13 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { } switch (I->getOpcode()) { - case Instruction::Freeze: { - // `freeze` is negatible if its operand is negatible. - Value *NegOp = negate(I->getOperand(0), Depth + 1); - if (!NegOp) // Early return. - return nullptr; - return Builder.CreateFreeze(NegOp, I->getName() + ".neg"); - } + case Instruction::Freeze: { + // `freeze` is negatible if its operand is negatible. + Value *NegOp = negate(I->getOperand(0), Depth + 1); + if (!NegOp) // Early return. + return nullptr; + return Builder.CreateFreeze(NegOp, I->getName() + ".neg"); + } case Instruction::PHI: { // `phi` is negatible if all the incoming values are negatible. auto *PHI = cast<PHINode>(I); @@ -285,16 +285,16 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { return NegatedPHI; } case Instruction::Select: { - if (isKnownNegation(I->getOperand(1), I->getOperand(2))) { - // Of one hand of select is known to be negation of another hand, - // just swap the hands around. - auto *NewSelect = cast<SelectInst>(I->clone()); - // Just swap the operands of the select. - NewSelect->swapValues(); - // Don't swap prof metadata, we didn't change the branch behavior. - NewSelect->setName(I->getName() + ".neg"); - Builder.Insert(NewSelect); - return NewSelect; + if (isKnownNegation(I->getOperand(1), I->getOperand(2))) { + // Of one hand of select is known to be negation of another hand, + // just swap the hands around. + auto *NewSelect = cast<SelectInst>(I->clone()); + // Just swap the operands of the select. + NewSelect->swapValues(); + // Don't swap prof metadata, we didn't change the branch behavior. + NewSelect->setName(I->getName() + ".neg"); + Builder.Insert(NewSelect); + return NewSelect; } // `select` is negatible if both hands of `select` are negatible. Value *NegOp1 = negate(I->getOperand(1), Depth + 1); @@ -350,81 +350,81 @@ LLVM_NODISCARD Value *Negator::visitImpl(Value *V, unsigned Depth) { } case Instruction::Shl: { // `shl` is negatible if the first operand is negatible. - if (Value *NegOp0 = negate(I->getOperand(0), Depth + 1)) - return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg"); - // Otherwise, `shl %x, C` can be interpreted as `mul %x, 1<<C`. - auto *Op1C = dyn_cast<Constant>(I->getOperand(1)); - if (!Op1C) // Early return. + if (Value *NegOp0 = negate(I->getOperand(0), Depth + 1)) + return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg"); + // Otherwise, `shl %x, C` can be interpreted as `mul %x, 1<<C`. + auto *Op1C = dyn_cast<Constant>(I->getOperand(1)); + if (!Op1C) // Early return. return nullptr; - return Builder.CreateMul( - I->getOperand(0), - ConstantExpr::getShl(Constant::getAllOnesValue(Op1C->getType()), Op1C), - I->getName() + ".neg"); + return Builder.CreateMul( + I->getOperand(0), + ConstantExpr::getShl(Constant::getAllOnesValue(Op1C->getType()), Op1C), + I->getName() + ".neg"); } - case Instruction::Or: { + case Instruction::Or: { if (!haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL, &AC, I, &DT)) return nullptr; // Don't know how to handle `or` in general. - std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); + std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); // `or`/`add` are interchangeable when operands have no common bits set. // `inc` is always negatible. - if (match(Ops[1], m_One())) - return Builder.CreateNot(Ops[0], I->getName() + ".neg"); + if (match(Ops[1], m_One())) + return Builder.CreateNot(Ops[0], I->getName() + ".neg"); // Else, just defer to Instruction::Add handling. LLVM_FALLTHROUGH; - } + } case Instruction::Add: { // `add` is negatible if both of its operands are negatible. - SmallVector<Value *, 2> NegatedOps, NonNegatedOps; - for (Value *Op : I->operands()) { - // Can we sink the negation into this operand? - if (Value *NegOp = negate(Op, Depth + 1)) { - NegatedOps.emplace_back(NegOp); // Successfully negated operand! - continue; - } - // Failed to sink negation into this operand. IFF we started from negation - // and we manage to sink negation into one operand, we can still do this. - if (!IsTrulyNegation) - return nullptr; - NonNegatedOps.emplace_back(Op); // Just record which operand that was. - } - assert((NegatedOps.size() + NonNegatedOps.size()) == 2 && - "Internal consistency sanity check."); - // Did we manage to sink negation into both of the operands? - if (NegatedOps.size() == 2) // Then we get to keep the `add`! - return Builder.CreateAdd(NegatedOps[0], NegatedOps[1], - I->getName() + ".neg"); - assert(IsTrulyNegation && "We should have early-exited then."); - // Completely failed to sink negation? - if (NonNegatedOps.size() == 2) + SmallVector<Value *, 2> NegatedOps, NonNegatedOps; + for (Value *Op : I->operands()) { + // Can we sink the negation into this operand? + if (Value *NegOp = negate(Op, Depth + 1)) { + NegatedOps.emplace_back(NegOp); // Successfully negated operand! + continue; + } + // Failed to sink negation into this operand. IFF we started from negation + // and we manage to sink negation into one operand, we can still do this. + if (!IsTrulyNegation) + return nullptr; + NonNegatedOps.emplace_back(Op); // Just record which operand that was. + } + assert((NegatedOps.size() + NonNegatedOps.size()) == 2 && + "Internal consistency sanity check."); + // Did we manage to sink negation into both of the operands? + if (NegatedOps.size() == 2) // Then we get to keep the `add`! + return Builder.CreateAdd(NegatedOps[0], NegatedOps[1], + I->getName() + ".neg"); + assert(IsTrulyNegation && "We should have early-exited then."); + // Completely failed to sink negation? + if (NonNegatedOps.size() == 2) return nullptr; - // 0-(a+b) --> (-a)-b - return Builder.CreateSub(NegatedOps[0], NonNegatedOps[0], - I->getName() + ".neg"); + // 0-(a+b) --> (-a)-b + return Builder.CreateSub(NegatedOps[0], NonNegatedOps[0], + I->getName() + ".neg"); } - case Instruction::Xor: { - std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); + case Instruction::Xor: { + std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); // `xor` is negatible if one of its operands is invertible. // FIXME: InstCombineInverter? But how to connect Inverter and Negator? - if (auto *C = dyn_cast<Constant>(Ops[1])) { - Value *Xor = Builder.CreateXor(Ops[0], ConstantExpr::getNot(C)); + if (auto *C = dyn_cast<Constant>(Ops[1])) { + Value *Xor = Builder.CreateXor(Ops[0], ConstantExpr::getNot(C)); return Builder.CreateAdd(Xor, ConstantInt::get(Xor->getType(), 1), I->getName() + ".neg"); } return nullptr; - } + } case Instruction::Mul: { - std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); + std::array<Value *, 2> Ops = getSortedOperandsOfBinOp(I); // `mul` is negatible if one of its operands is negatible. Value *NegatedOp, *OtherOp; // First try the second operand, in case it's a constant it will be best to // just invert it instead of sinking the `neg` deeper. - if (Value *NegOp1 = negate(Ops[1], Depth + 1)) { + if (Value *NegOp1 = negate(Ops[1], Depth + 1)) { NegatedOp = NegOp1; - OtherOp = Ops[0]; - } else if (Value *NegOp0 = negate(Ops[0], Depth + 1)) { + OtherOp = Ops[0]; + } else if (Value *NegOp0 = negate(Ops[0], Depth + 1)) { NegatedOp = NegOp0; - OtherOp = Ops[1]; + OtherOp = Ops[1]; } else // Can't negate either of them. return nullptr; @@ -487,7 +487,7 @@ LLVM_NODISCARD Optional<Negator::Result> Negator::run(Value *Root) { } LLVM_NODISCARD Value *Negator::Negate(bool LHSIsZero, Value *Root, - InstCombinerImpl &IC) { + InstCombinerImpl &IC) { ++NegatorTotalNegationsAttempted; LLVM_DEBUG(dbgs() << "Negator: attempting to sink negation into " << *Root << "\n"); |