Skip to content

Commit 0b83c5a

Browse files
committed
[InstCombine] Combine neg of shl of sub (PR44529)
Fixes https://bugs.llvm.org/show_bug.cgi?id=44529. We already have a combine to sink a negation through a left-shift, but it currently only works if the shift operand is negatable without creating any instructions. This patch introduces freelyNegateValue() as a more powerful extension of dyn_castNegVal(), which allows negating a value as long as this doesn't end up increasing instruction count. Specifically, this patch adds support for negating A-B to B-A. This mechanism could in the future be extended to handle general negation chains that a) start at a proper 0-X negation and b) only require one operand to be freely negatable. This would end up as a weaker form of D68408 aimed at the most obviously profitable subset that eliminates a negation entirely. Differential Revision: https://reviews.llvm.org/D72978
1 parent 80c34f9 commit 0b83c5a

File tree

4 files changed

+21
-4
lines changed

4 files changed

+21
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
19851985

19861986
// 0 - (X << Y) -> (-X << Y) when X is freely negatable.
19871987
if (match(Op1, m_Shl(m_Value(X), m_Value(Y))) && match(Op0, m_Zero()))
1988-
if (Value *XNeg = dyn_castNegVal(X))
1988+
if (Value *XNeg = freelyNegateValue(X))
19891989
return BinaryOperator::CreateShl(XNeg, Y);
19901990

19911991
// Subtracting -1/0 is the same as adding 1/0:

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
474474
bool shouldChangeType(unsigned FromBitWidth, unsigned ToBitWidth) const;
475475
bool shouldChangeType(Type *From, Type *To) const;
476476
Value *dyn_castNegVal(Value *V) const;
477+
Value *freelyNegateValue(Value *V);
477478
Type *FindElementAtOffset(PointerType *PtrTy, int64_t Offset,
478479
SmallVectorImpl<Value *> &NewIndices);
479480

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,23 @@ Value *InstCombiner::dyn_castNegVal(Value *V) const {
856856
return nullptr;
857857
}
858858

859+
/// Get negated V (that is 0-V) without increasing instruction count,
860+
/// assuming that the original V will become unused.
861+
Value *InstCombiner::freelyNegateValue(Value *V) {
862+
if (Value *NegV = dyn_castNegVal(V))
863+
return NegV;
864+
865+
if (!V->hasOneUse())
866+
return nullptr;
867+
868+
Value *A, *B;
869+
// 0-(A-B) => B-A
870+
if (match(V, m_Sub(m_Value(A), m_Value(B))))
871+
return Builder.CreateSub(B, A);
872+
873+
return nullptr;
874+
}
875+
859876
static Value *foldOperationIntoSelectOperand(Instruction &I, Value *SO,
860877
InstCombiner::BuilderTy &Builder) {
861878
if (auto *Cast = dyn_cast<CastInst>(&I))

llvm/test/Transforms/InstCombine/sub.ll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,8 @@ define i32 @test26(i32 %x) {
543543

544544
define i64 @test_neg_shl_sub(i64 %a, i64 %b) {
545545
; CHECK-LABEL: @test_neg_shl_sub(
546-
; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]
547-
; CHECK-NEXT: [[MUL:%.*]] = shl i64 [[SUB]], 2
548-
; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]]
546+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]
547+
; CHECK-NEXT: [[NEG:%.*]] = shl i64 [[TMP1]], 2
549548
; CHECK-NEXT: ret i64 [[NEG]]
550549
;
551550
%sub = sub i64 %a, %b

0 commit comments

Comments
 (0)