Skip to content

Commit a677651

Browse files
committedAug 8, 2018
[InstCombine] De Morgan: sink 'not' into 'xor' (PR38446)
Summary: https://rise4fun.com/Alive/IT3 Comes up in the [most ugliest] `signed int` -> `signed char` case of `-fsanitize=implicit-conversion` (https://reviews.llvm.org/D50250) Previously, we were stuck with `not`: {F6867736} But now we are able to completely get rid of it: {F6867737} (FIXME: why are we loosing the metadata? that seems wrong/strange.) Here, we only want to do that it we will be able to completely get rid of that 'not'. Reviewers: spatel, craig.topper Reviewed By: spatel Subscribers: vsk, erichkeane, llvm-commits Differential Revision: https://reviews.llvm.org/D50301 llvm-svn: 339243
1 parent f8c394f commit a677651

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed
 

‎llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,32 @@ static Instruction *visitMaskedMerge(BinaryOperator &I,
24522452
return nullptr;
24532453
}
24542454

2455+
// Transform
2456+
// ~(x ^ y)
2457+
// into:
2458+
// (~x) ^ y
2459+
// or into
2460+
// x ^ (~y)
2461+
static Instruction *sinkNotIntoXor(BinaryOperator &I,
2462+
InstCombiner::BuilderTy &Builder) {
2463+
Value *X, *Y;
2464+
// FIXME: one-use check is not needed in general, but currently we are unable
2465+
// to fold 'not' into 'icmp', if that 'icmp' has multiple uses. (D35182)
2466+
if (!match(&I, m_Not(m_OneUse(m_Xor(m_Value(X), m_Value(Y))))))
2467+
return nullptr;
2468+
2469+
// We only want to do the transform if it is free to do.
2470+
if (IsFreeToInvert(X, X->hasOneUse())) {
2471+
// Ok, good.
2472+
} else if (IsFreeToInvert(Y, Y->hasOneUse())) {
2473+
std::swap(X, Y);
2474+
} else
2475+
return nullptr;
2476+
2477+
Value *NotX = Builder.CreateNot(X, X->getName() + ".not");
2478+
return BinaryOperator::CreateXor(NotX, Y, I.getName() + ".demorgan");
2479+
}
2480+
24552481
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
24562482
// here. We should standardize that construct where it is needed or choose some
24572483
// other way to ensure that commutated variants of patterns are not missed.
@@ -2777,5 +2803,8 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
27772803
}
27782804
}
27792805

2806+
if (Instruction *NewXor = sinkNotIntoXor(I, Builder))
2807+
return NewXor;
2808+
27802809
return nullptr;
27812810
}

‎llvm/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll

+6-9
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ declare i1 @gen1()
2323
define i1 @positive_easyinvert(i16 %x, i8 %y) {
2424
; CHECK-LABEL: @positive_easyinvert(
2525
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i16 [[X:%.*]], 0
26-
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
27-
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], [[TMP1]]
28-
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
26+
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[Y:%.*]], -1
27+
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP1]], [[TMP2]]
2928
; CHECK-NEXT: ret i1 [[TMP4]]
3029
;
3130
%tmp1 = icmp slt i16 %x, 0
@@ -38,9 +37,8 @@ define i1 @positive_easyinvert(i16 %x, i8 %y) {
3837
define i1 @positive_easyinvert0(i8 %y) {
3938
; CHECK-LABEL: @positive_easyinvert0(
4039
; CHECK-NEXT: [[TMP1:%.*]] = call i1 @gen1()
41-
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
42-
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], [[TMP1]]
43-
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
40+
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[Y:%.*]], -1
41+
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP1]], [[TMP2]]
4442
; CHECK-NEXT: ret i1 [[TMP4]]
4543
;
4644
%tmp1 = call i1 @gen1()
@@ -53,9 +51,8 @@ define i1 @positive_easyinvert0(i8 %y) {
5351
define i1 @positive_easyinvert1(i8 %y) {
5452
; CHECK-LABEL: @positive_easyinvert1(
5553
; CHECK-NEXT: [[TMP1:%.*]] = call i1 @gen1()
56-
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
57-
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP1]], [[TMP2]]
58-
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
54+
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[Y:%.*]], -1
55+
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP1]], [[TMP2]]
5956
; CHECK-NEXT: ret i1 [[TMP4]]
6057
;
6158
%tmp1 = call i1 @gen1()

0 commit comments

Comments
 (0)
Please sign in to comment.