Skip to content

Commit a000435

Browse files
committed
[InstCombine] Negator: 'or' with no common bits set is just 'add'
In `InstCombiner::visitAdd()`, we have ``` // A+B --> A|B iff A and B have no bits set in common. if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) return BinaryOperator::CreateOr(LHS, RHS); ``` so we should handle such `or`'s here, too.
1 parent a5f22f2 commit a000435

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,9 +1033,14 @@ class Negator final {
10331033
using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
10341034
BuilderTy Builder;
10351035

1036+
const DataLayout &DL;
1037+
AssumptionCache &AC;
1038+
const DominatorTree &DT;
1039+
10361040
const bool IsTrulyNegation;
10371041

1038-
Negator(LLVMContext &C, const DataLayout &DL, bool IsTrulyNegation);
1042+
Negator(LLVMContext &C, const DataLayout &DL, AssumptionCache &AC,
1043+
const DominatorTree &DT, bool IsTrulyNegation);
10391044

10401045
#if LLVM_ENABLE_STATS
10411046
unsigned NumValuesVisitedInThisNegator = 0;

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
#include <tuple>
4747
#include <utility>
4848

49+
namespace llvm {
50+
class AssumptionCache;
51+
class DataLayout;
52+
class DominatorTree;
53+
class LLVMContext;
54+
} // namespace llvm
55+
4956
using namespace llvm;
5057

5158
#define DEBUG_TYPE "instcombine"
@@ -87,13 +94,14 @@ static cl::opt<unsigned>
8794
cl::desc("What is the maximal lookup depth when trying to "
8895
"check for viability of negation sinking."));
8996

90-
Negator::Negator(LLVMContext &C, const DataLayout &DL, bool IsTrulyNegation_)
91-
: Builder(C, TargetFolder(DL),
97+
Negator::Negator(LLVMContext &C, const DataLayout &DL_, AssumptionCache &AC_,
98+
const DominatorTree &DT_, bool IsTrulyNegation_)
99+
: Builder(C, TargetFolder(DL_),
92100
IRBuilderCallbackInserter([&](Instruction *I) {
93101
++NegatorNumInstructionsCreatedTotal;
94102
NewInstructions.push_back(I);
95103
})),
96-
IsTrulyNegation(IsTrulyNegation_) {}
104+
DL(DL_), AC(AC_), DT(DT_), IsTrulyNegation(IsTrulyNegation_) {}
97105

98106
#if LLVM_ENABLE_STATS
99107
Negator::~Negator() {
@@ -301,6 +309,16 @@ LLVM_NODISCARD Value *Negator::visit(Value *V, unsigned Depth) {
301309
return nullptr;
302310
return Builder.CreateShl(NegOp0, I->getOperand(1), I->getName() + ".neg");
303311
}
312+
case Instruction::Or:
313+
if (!haveNoCommonBitsSet(I->getOperand(0), I->getOperand(1), DL, &AC, I,
314+
&DT))
315+
return nullptr; // Don't know how to handle `or` in general.
316+
// `or`/`add` are interchangeable when operands have no common bits set.
317+
// `inc` is always negatible.
318+
if (match(I->getOperand(1), m_One()))
319+
return Builder.CreateNot(I->getOperand(0), I->getName() + ".neg");
320+
// Else, just defer to Instruction::Add handling.
321+
LLVM_FALLTHROUGH;
304322
case Instruction::Add: {
305323
// `add` is negatible if both of its operands are negatible.
306324
Value *NegOp0 = visit(I->getOperand(0), Depth + 1);
@@ -364,7 +382,8 @@ LLVM_NODISCARD Value *Negator::Negate(bool LHSIsZero, Value *Root,
364382
if (!NegatorEnabled || !DebugCounter::shouldExecute(NegatorCounter))
365383
return nullptr;
366384

367-
Negator N(Root->getContext(), IC.getDataLayout(), LHSIsZero);
385+
Negator N(Root->getContext(), IC.getDataLayout(), IC.getAssumptionCache(),
386+
IC.getDominatorTree(), LHSIsZero);
368387
Optional<Result> Res = N.run(Root);
369388
if (!Res) { // Negation failed.
370389
LLVM_DEBUG(dbgs() << "Negator: failed to sink negation into " << *Root

llvm/test/Transforms/InstCombine/sub-of-negatible.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,8 @@ nonneg_bb:
827827
define i8 @negation_of_increment_via_or_with_no_common_bits_set(i8 %x, i8 %y) {
828828
; CHECK-LABEL: @negation_of_increment_via_or_with_no_common_bits_set(
829829
; CHECK-NEXT: [[T0:%.*]] = shl i8 [[Y:%.*]], 1
830-
; CHECK-NEXT: [[T1:%.*]] = or i8 [[T0]], 1
831-
; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X:%.*]], [[T1]]
830+
; CHECK-NEXT: [[T1_NEG:%.*]] = xor i8 [[T0]], -1
831+
; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X:%.*]]
832832
; CHECK-NEXT: ret i8 [[T2]]
833833
;
834834
%t0 = shl i8 %y, 1
@@ -868,9 +868,9 @@ define i8 @add_via_or_with_no_common_bits_set(i8 %x, i8 %y) {
868868
; CHECK-LABEL: @add_via_or_with_no_common_bits_set(
869869
; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y:%.*]]
870870
; CHECK-NEXT: call void @use8(i8 [[T0]])
871-
; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 2
872-
; CHECK-NEXT: [[T2:%.*]] = or i8 [[T1]], 3
873-
; CHECK-NEXT: [[T3:%.*]] = sub i8 [[X:%.*]], [[T2]]
871+
; CHECK-NEXT: [[T1_NEG:%.*]] = shl i8 [[Y]], 2
872+
; CHECK-NEXT: [[T2_NEG:%.*]] = add i8 [[T1_NEG]], -3
873+
; CHECK-NEXT: [[T3:%.*]] = add i8 [[T2_NEG]], [[X:%.*]]
874874
; CHECK-NEXT: ret i8 [[T3]]
875875
;
876876
%t0 = sub i8 0, %y

0 commit comments

Comments
 (0)