// In some cases we can give the answer without further recursion.
switch (I->getOpcode()) {
- case Instruction::Sub:
- // `sub` is always negatible.
- return Builder.CreateSub(I->getOperand(1), I->getOperand(0),
- I->getName() + ".neg");
case Instruction::Add:
// `inc` is always negatible.
if (match(I->getOperand(1), m_One()))
}
break;
}
+ case Instruction::SExt:
+ case Instruction::ZExt:
+ // `*ext` of i1 is always negatible
+ if (I->getOperand(0)->getType()->isIntOrIntVectorTy(1))
+ return I->getOpcode() == Instruction::SExt
+ ? Builder.CreateZExt(I->getOperand(0), I->getType(),
+ I->getName() + ".neg")
+ : Builder.CreateSExt(I->getOperand(0), I->getType(),
+ I->getName() + ".neg");
+ break;
+ default:
+ break; // Other instructions require recursive reasoning.
+ }
+
+ // Some other cases, while still don't require recursion,
+ // are restricted to the one-use case.
+ if (!V->hasOneUse())
+ return nullptr;
+
+ switch (I->getOpcode()) {
+ case Instruction::Sub:
+ // `sub` is always negatible.
+ // But if the old `sub` sticks around, even thought we don't increase
+ // instruction count, this is a likely regression since we increased
+ // live-range of *both* of the operands, which might lead to more spilling.
+ return Builder.CreateSub(I->getOperand(1), I->getOperand(0),
+ I->getName() + ".neg");
case Instruction::SDiv:
// `sdiv` is negatible if divisor is not undef/INT_MIN/1.
// While this is normally not behind a use-check,
// let's consider division to be special since it's costly.
- if (!I->hasOneUse())
- break;
if (auto *Op1C = dyn_cast<Constant>(I->getOperand(1))) {
if (!Op1C->containsUndefElement() && Op1C->isNotMinSignedValue() &&
Op1C->isNotOneValue()) {
}
}
break;
- case Instruction::SExt:
- case Instruction::ZExt:
- // `*ext` of i1 is always negatible
- if (I->getOperand(0)->getType()->isIntOrIntVectorTy(1))
- return I->getOpcode() == Instruction::SExt
- ? Builder.CreateZExt(I->getOperand(0), I->getType(),
- I->getName() + ".neg")
- : Builder.CreateSExt(I->getOperand(0), I->getType(),
- I->getName() + ".neg");
- break;
- default:
- break; // Other instructions require recursive reasoning.
}
- // Rest of the logic is recursive, and if either the current instruction
- // has other uses or if it's time to give up then it's time.
- if (!V->hasOneUse())
- return nullptr;
+ // Rest of the logic is recursive, so if it's time to give up then it's time.
if (Depth > NegatorMaxDepth) {
LLVM_DEBUG(dbgs() << "Negator: reached maximal allowed traversal depth in "
<< *V << ". Giving up.\n");
define i64 @test_neg_shl_sub_extra_use1(i64 %a, i64 %b, i64* %p) {
; CHECK-LABEL: @test_neg_shl_sub_extra_use1(
-; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]
-; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A]], [[B]]
+; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: store i64 [[SUB]], i64* [[P:%.*]], align 8
-; CHECK-NEXT: [[MUL_NEG:%.*]] = shl i64 [[SUB_NEG]], 2
-; CHECK-NEXT: ret i64 [[MUL_NEG]]
+; CHECK-NEXT: [[MUL:%.*]] = shl i64 [[SUB]], 2
+; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]]
+; CHECK-NEXT: ret i64 [[NEG]]
;
%sub = sub i64 %a, %b
store i64 %sub, i64* %p