50#define DEBUG_TYPE "instcombine"
53 "Negator: Number of negations attempted to be sinked");
55 "Negator: Number of negations successfully sinked");
56STATISTIC(NegatorMaxDepthVisited,
"Negator: Maximal traversal depth ever "
57 "reached while attempting to sink negation");
59 "Negator: How many times did the traversal depth limit was reached "
62 NegatorNumValuesVisited,
63 "Negator: Total number of values visited during attempts to sink negation");
65 "Negator: How many negations did we retrieve/reuse from cache");
67 "Negator: Maximal number of values ever visited while attempting to "
70 "Negator: Number of new negated instructions created, total");
72 "Negator: Maximal number of new instructions created during negation "
75 "Negator: Number of new negated instructions created in successful "
76 "negation sinking attempts");
79 "Controls Negator transformations in InstCombine pass");
82 bool IsTrulyNegation_,
unsigned MaxDepth)
85 ++NegatorNumInstructionsCreatedTotal;
86 NewInstructions.push_back(
I);
88 DT(DT_), IsTrulyNegation(IsTrulyNegation_), MaxDepth(MaxDepth) {}
92 NegatorMaxTotalValuesVisited.updateMax(NumValuesVisitedInThisNegator);
100std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(
Instruction *
I) {
101 assert(
I->getNumOperands() == 2 &&
"Only for binops!");
102 std::array<Value *, 2>
Ops{
I->getOperand(0),
I->getOperand(1)};
111[[nodiscard]]
Value *Negator::visitImpl(
Value *V,
bool IsNSW,
unsigned Depth) {
117 if (
V->getType()->isIntOrIntVectorTy(1))
138 if (!
V->hasOneUse() && !IsTrulyNegation)
142 unsigned BitWidth =
I->getType()->getScalarSizeInBits();
146 InstCombiner::BuilderTy::InsertPointGuard Guard(Builder);
149 Builder.SetInsertPoint(
I);
152 switch (
I->getOpcode()) {
153 case Instruction::Add: {
154 std::array<Value *, 2>
Ops = getSortedOperandsOfBinOp(
I);
157 return Builder.CreateNot(
Ops[0],
I->getName() +
".neg");
160 case Instruction::Xor:
163 return Builder.CreateAdd(
X, ConstantInt::get(
X->getType(), 1),
164 I->getName() +
".neg");
166 case Instruction::AShr:
167 case Instruction::LShr: {
171 Value *BO =
I->getOpcode() == Instruction::AShr
172 ? Builder.CreateLShr(
I->getOperand(0),
I->getOperand(1))
173 : Builder.CreateAShr(
I->getOperand(0),
I->getOperand(1));
175 NewInstr->copyIRFlags(
I);
176 NewInstr->setName(
I->getName() +
".neg");
186 case Instruction::SExt:
187 case Instruction::ZExt:
189 if (
I->getOperand(0)->getType()->isIntOrIntVectorTy(1))
190 return I->getOpcode() == Instruction::SExt
191 ? Builder.CreateZExt(
I->getOperand(0),
I->getType(),
192 I->getName() +
".neg")
193 : Builder.CreateSExt(
I->getOperand(0),
I->getType(),
194 I->getName() +
".neg");
196 case Instruction::Select: {
205 return Builder.CreateSelect(Sel->getCondition(), NegTrueC, NegFalseC,
206 I->getName() +
".neg",
I);
210 case Instruction::Call:
212 return Builder.CreateIntrinsic(CI->getType(), CI->getIntrinsicID(),
213 {CI->getRHS(), CI->getLHS()});
219 if (
I->getOpcode() == Instruction::Sub &&
224 return Builder.CreateSub(
I->getOperand(1),
I->getOperand(0),
225 I->getName() +
".neg",
false,
226 IsNSW &&
I->hasNoSignedWrap());
234 switch (
I->getOpcode()) {
235 case Instruction::ZExt: {
238 Value *SrcOp =
I->getOperand(0);
240 const APInt &FullShift = APInt(SrcWidth, SrcWidth - 1);
241 if (IsTrulyNegation &&
243 Value *Ashr = Builder.CreateAShr(
X, FullShift);
244 return Builder.CreateSExt(Ashr,
I->getType());
248 case Instruction::And: {
257 if (IsTrulyNegation &&
261 unsigned BW =
X->getType()->getScalarSizeInBits();
262 Constant *BWMinusOne = ConstantInt::get(
X->getType(), BW - 1);
263 Value *
R = Builder.CreateShl(
X, Builder.CreateSub(BWMinusOne, ShAmt));
264 R = Builder.CreateAShr(R, BWMinusOne);
265 return Builder.CreateTruncOrBitCast(R,
I->getType());
269 case Instruction::SDiv:
274 if (!Op1C->containsUndefOrPoisonElement() &&
275 Op1C->isNotMinSignedValue() && Op1C->isNotOneValue()) {
280 NewInstr->setIsExact(
I->isExact());
288 if (
Depth > MaxDepth) {
289 LLVM_DEBUG(
dbgs() <<
"Negator: reached maximal allowed traversal depth in "
290 << *V <<
". Giving up.\n");
291 ++NegatorTimesDepthLimitReached;
295 switch (
I->getOpcode()) {
296 case Instruction::Freeze: {
298 Value *NegOp = negate(
I->getOperand(0), IsNSW,
Depth + 1);
301 return Builder.CreateFreeze(NegOp,
I->getName() +
".neg");
303 case Instruction::PHI: {
306 SmallVector<Value *, 4> NegatedIncomingValues(
PHI->getNumOperands());
307 for (
auto I :
zip(
PHI->incoming_values(), NegatedIncomingValues)) {
309 if (DT.dominates(
PHI->getParent(), std::get<0>(
I)))
311 if (!(std::get<1>(
I) =
312 negate(std::get<0>(
I), IsNSW,
Depth + 1)))
316 PHINode *NegatedPHI = Builder.CreatePHI(
317 PHI->getType(),
PHI->getNumOperands(),
PHI->getName() +
".neg");
318 for (
auto I :
zip(NegatedIncomingValues,
PHI->blocks()))
322 case Instruction::Select: {
329 NewSelect->swapValues();
331 NewSelect->setName(
I->getName() +
".neg");
333 Value *TV = NewSelect->getTrueValue();
334 Value *FV = NewSelect->getFalseValue();
343 Builder.Insert(NewSelect);
347 Value *NegOp1 = negate(
I->getOperand(1), IsNSW,
Depth + 1);
350 Value *NegOp2 = negate(
I->getOperand(2), IsNSW,
Depth + 1);
354 return Builder.CreateSelect(
I->getOperand(0), NegOp1, NegOp2,
355 I->getName() +
".neg",
I);
357 case Instruction::ShuffleVector: {
360 Value *NegOp0 = negate(
I->getOperand(0), IsNSW,
Depth + 1);
363 Value *NegOp1 = negate(
I->getOperand(1), IsNSW,
Depth + 1);
366 return Builder.CreateShuffleVector(NegOp0, NegOp1, Shuf->getShuffleMask(),
367 I->getName() +
".neg");
369 case Instruction::ExtractElement: {
372 Value *NegVector = negate(EEI->getVectorOperand(), IsNSW,
Depth + 1);
375 return Builder.CreateExtractElement(NegVector, EEI->getIndexOperand(),
376 I->getName() +
".neg");
378 case Instruction::InsertElement: {
382 Value *NegVector = negate(IEI->getOperand(0), IsNSW,
Depth + 1);
385 Value *NegNewElt = negate(IEI->getOperand(1), IsNSW,
Depth + 1);
388 return Builder.CreateInsertElement(NegVector, NegNewElt, IEI->getOperand(2),
389 I->getName() +
".neg");
391 case Instruction::Trunc: {
393 Value *NegOp = negate(
I->getOperand(0),
false,
Depth + 1);
396 return Builder.CreateTrunc(NegOp,
I->getType(),
I->getName() +
".neg");
398 case Instruction::Shl: {
400 IsNSW &=
I->hasNoSignedWrap();
401 if (
Value *NegOp0 = negate(
I->getOperand(0), IsNSW,
Depth + 1))
402 return Builder.CreateShl(NegOp0,
I->getOperand(1),
I->getName() +
".neg",
408 return Builder.CreateMul(
411 I->getName() +
".neg",
false, IsNSW);
413 case Instruction::Or: {
416 std::array<Value *, 2>
Ops = getSortedOperandsOfBinOp(
I);
420 return Builder.CreateNot(
Ops[0],
I->getName() +
".neg");
424 case Instruction::Add: {
426 SmallVector<Value *, 2> NegatedOps, NonNegatedOps;
435 if (!IsTrulyNegation)
440 "Internal consistency check failed.");
442 if (NegatedOps.
size() == 2)
443 return Builder.CreateAdd(NegatedOps[0], NegatedOps[1],
444 I->getName() +
".neg");
445 assert(IsTrulyNegation &&
"We should have early-exited then.");
447 if (NonNegatedOps.
size() == 2)
450 return Builder.CreateSub(NegatedOps[0], NonNegatedOps[0],
451 I->getName() +
".neg");
453 case Instruction::Xor: {
454 std::array<Value *, 2>
Ops = getSortedOperandsOfBinOp(
I);
458 if (IsTrulyNegation) {
460 return Builder.CreateAdd(
Xor, ConstantInt::get(
Xor->getType(), 1),
461 I->getName() +
".neg");
466 case Instruction::Mul: {
467 std::array<Value *, 2>
Ops = getSortedOperandsOfBinOp(
I);
469 Value *NegatedOp, *OtherOp;
475 }
else if (
Value *NegOp0 = negate(
Ops[0],
false,
Depth + 1)) {
481 return Builder.CreateMul(NegatedOp, OtherOp,
I->getName() +
".neg",
482 false, IsNSW &&
I->hasNoSignedWrap());
491[[nodiscard]]
Value *Negator::negate(
Value *V,
bool IsNSW,
unsigned Depth) {
492 NegatorMaxDepthVisited.updateMax(
Depth);
493 ++NegatorNumValuesVisited;
496 ++NumValuesVisitedInThisNegator;
501 Value *Placeholder =
reinterpret_cast<Value *
>(
static_cast<uintptr_t
>(-1));
505 auto NegationsCacheIterator = NegationsCache.find(V);
506 if (NegationsCacheIterator != NegationsCache.end()) {
507 ++NegatorNumNegationsFoundInCache;
508 Value *NegatedV = NegationsCacheIterator->second;
509 assert(NegatedV != Placeholder &&
"Encountered a cycle during negation.");
517 NegationsCache[
V] = Placeholder;
523 NegationsCache[
V] = NegatedV;
528[[nodiscard]] std::optional<Negator::Result> Negator::run(
Value *Root,
530 Value *Negated = negate(Root, IsNSW, 0);
535 I->eraseFromParent();
538 return std::make_pair(ArrayRef<Instruction *>(NewInstructions), Negated);
543 ++NegatorTotalNegationsAttempted;
544 LLVM_DEBUG(
dbgs() <<
"Negator: attempting to sink negation into " << *Root
547 if (!IC.
CLOpts.negator_enabled ||
552 LHSIsZero, IC.
CLOpts.negator_max_depth);
553 std::optional<Result> Res =
N.run(Root, IsNSW);
555 LLVM_DEBUG(
dbgs() <<
"Negator: failed to sink negation into " << *Root
560 LLVM_DEBUG(
dbgs() <<
"Negator: successfully sunk negation into " << *Root
561 <<
"\n NEW: " << *Res->second <<
"\n");
562 ++NegatorNumTreesNegated;
567 <<
" instrs to InstCombine\n");
568 NegatorMaxInstructionsCreated.updateMax(Res->first.size());
569 NegatorNumInstructionsNegatedSuccess += Res->first.size();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This defines the Use class.
This file provides internal interfaces used to implement the InstCombine.
This file provides the interface for the instcombine pass implementation.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static LLVM_ABI Constant * getNot(Constant *C)
static LLVM_ABI Constant * getNeg(Constant *C, bool HasNSW=false)
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
A parsed version of the target data layout string in and methods for querying it.
static bool shouldExecute(CounterInfo &Counter)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
const InstCombineCLOptions & CLOpts
const DataLayout & getDataLayout() const
DominatorTree & getDominatorTree() const
static unsigned getComplexity(Value *V)
Assign a complexity or rank value to LLVM Values.
void addToWorklist(Instruction *I)
This is an important class for using LLVM in a threaded context.
static Value * Negate(bool LHSIsZero, bool IsNSW, Value *Root, InstCombinerImpl &IC)
Attempt to negate Root.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
reference emplace_back(ArgTypes &&... Args)
TargetFolder - Create constants with target dependent folding.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, TruncInst >, OpTy > m_TruncOrSelf(const OpTy &Op)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
specific_intval< true > m_SpecificIntAllowPoison(const APInt &V)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
cst_pred_ty< is_any_apint > m_AnyIntegralConstant()
Match an integer or vector with any integral constant.
auto m_Value()
Match an arbitrary value and ignore it.
match_immconstant_ty m_ImmConstant()
Match an arbitrary immediate Constant and ignore it.
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
auto m_Undef()
Match an arbitrary undef constant.
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ Xor
Bitwise or logical XOR of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isKnownNegation(const Value *X, const Value *Y, bool NeedNSW=false, bool AllowPoison=true)
Return true if the two given values are negation.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.