diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2018-08-08 13:31:19 +0000 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2018-08-08 13:31:19 +0000 |
commit | a677651a5a91a6d7ddfb5d168d92c9e7b7ff9755 (patch) | |
tree | 0205a6df42ea0fb4923fff7bce7388d6b5761ad9 /llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | |
parent | f8c394f0f5d7be43a4d9ab1d384da9112de57cb2 (diff) | |
download | bcm5719-llvm-a677651a5a91a6d7ddfb5d168d92c9e7b7ff9755.tar.gz bcm5719-llvm-a677651a5a91a6d7ddfb5d168d92c9e7b7ff9755.zip |
[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
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 3d758e2fe7c..8bca658ce43 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2452,6 +2452,32 @@ static Instruction *visitMaskedMerge(BinaryOperator &I, return nullptr; } +// Transform +// ~(x ^ y) +// into: +// (~x) ^ y +// or into +// x ^ (~y) +static Instruction *sinkNotIntoXor(BinaryOperator &I, + InstCombiner::BuilderTy &Builder) { + Value *X, *Y; + // FIXME: one-use check is not needed in general, but currently we are unable + // to fold 'not' into 'icmp', if that 'icmp' has multiple uses. (D35182) + if (!match(&I, m_Not(m_OneUse(m_Xor(m_Value(X), m_Value(Y)))))) + return nullptr; + + // We only want to do the transform if it is free to do. + if (IsFreeToInvert(X, X->hasOneUse())) { + // Ok, good. + } else if (IsFreeToInvert(Y, Y->hasOneUse())) { + std::swap(X, Y); + } else + return nullptr; + + Value *NotX = Builder.CreateNot(X, X->getName() + ".not"); + return BinaryOperator::CreateXor(NotX, Y, I.getName() + ".demorgan"); +} + // FIXME: We use commutative matchers (m_c_*) for some, but not all, matches // here. We should standardize that construct where it is needed or choose some // other way to ensure that commutated variants of patterns are not missed. @@ -2777,5 +2803,8 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { } } + if (Instruction *NewXor = sinkNotIntoXor(I, Builder)) + return NewXor; + return nullptr; } |