Skip to content

Commit 2e4d2f8

Browse files
rotaterightmemfrob
authored andcommitted
[InstCombine] fold not+or+neg
~((-X) | Y) --> (X - 1) & (~Y) We generally prefer 'add' over 'sub', this reduces the dependency chain, and this looks better for codegen on x86, ARM, and AArch64 targets. https://llvm.org/PR45755 https://alive2.llvm.org/ce/z/cxZDSp
1 parent b24b940 commit 2e4d2f8

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,14 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
32043204
if (isa<Constant>(X) || NotVal->hasOneUse())
32053205
return BinaryOperator::CreateAdd(Builder.CreateNot(X), Y);
32063206

3207+
// ~((-X) | Y) --> (X - 1) & (~Y)
3208+
if (match(NotVal,
3209+
m_OneUse(m_c_Or(m_OneUse(m_Neg(m_Value(X))), m_Value(Y))))) {
3210+
Value *DecX = Builder.CreateAdd(X, ConstantInt::getAllOnesValue(Ty));
3211+
Value *NotY = Builder.CreateNot(Y);
3212+
return BinaryOperator::CreateAnd(DecX, NotY);
3213+
}
3214+
32073215
// ~(~X >>s Y) --> (X >>s Y)
32083216
if (match(NotVal, m_AShr(m_Not(m_Value(X)), m_Value(Y))))
32093217
return BinaryOperator::CreateAShr(X, Y);

llvm/test/Transforms/InstCombine/not.ll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,9 @@ define i1 @not_select_cmpf_extra_use(i1 %x, i32 %z, i32 %w, i1 %cond) {
408408

409409
define i8 @not_or_neg(i8 %x, i8 %y) {
410410
; CHECK-LABEL: @not_or_neg(
411-
; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[Y:%.*]]
412-
; CHECK-NEXT: [[O:%.*]] = or i8 [[S]], [[X:%.*]]
413-
; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[O]], -1
411+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
412+
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X:%.*]], -1
413+
; CHECK-NEXT: [[NOT:%.*]] = and i8 [[TMP1]], [[TMP2]]
414414
; CHECK-NEXT: ret i8 [[NOT]]
415415
;
416416
%s = sub i8 0, %y
@@ -422,9 +422,9 @@ define i8 @not_or_neg(i8 %x, i8 %y) {
422422
define <3 x i5> @not_or_neg_commute_vec(<3 x i5> %x, <3 x i5> %p) {
423423
; CHECK-LABEL: @not_or_neg_commute_vec(
424424
; CHECK-NEXT: [[Y:%.*]] = mul <3 x i5> [[P:%.*]], <i5 1, i5 2, i5 3>
425-
; CHECK-NEXT: [[S:%.*]] = sub <3 x i5> <i5 0, i5 0, i5 undef>, [[X:%.*]]
426-
; CHECK-NEXT: [[O:%.*]] = or <3 x i5> [[Y]], [[S]]
427-
; CHECK-NEXT: [[NOT:%.*]] = xor <3 x i5> [[O]], <i5 -1, i5 undef, i5 -1>
425+
; CHECK-NEXT: [[TMP1:%.*]] = add <3 x i5> [[X:%.*]], <i5 -1, i5 -1, i5 -1>
426+
; CHECK-NEXT: [[TMP2:%.*]] = xor <3 x i5> [[Y]], <i5 -1, i5 -1, i5 -1>
427+
; CHECK-NEXT: [[NOT:%.*]] = and <3 x i5> [[TMP1]], [[TMP2]]
428428
; CHECK-NEXT: ret <3 x i5> [[NOT]]
429429
;
430430
%y = mul <3 x i5> %p, <i5 1, i5 2, i5 3> ; thwart complexity-based-canonicalization
@@ -434,6 +434,8 @@ define <3 x i5> @not_or_neg_commute_vec(<3 x i5> %x, <3 x i5> %p) {
434434
ret <3 x i5> %not
435435
}
436436

437+
; negative test
438+
437439
define i8 @not_or_neg_use1(i8 %x, i8 %y) {
438440
; CHECK-LABEL: @not_or_neg_use1(
439441
; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[Y:%.*]]
@@ -449,6 +451,8 @@ define i8 @not_or_neg_use1(i8 %x, i8 %y) {
449451
ret i8 %not
450452
}
451453

454+
; negative test
455+
452456
define i8 @not_or_neg_use2(i8 %x, i8 %y) {
453457
; CHECK-LABEL: @not_or_neg_use2(
454458
; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[Y:%.*]]

0 commit comments

Comments
 (0)