summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorCharlie Turner <charlie.turner@arm.com>2015-09-24 10:24:58 +0000
committerCharlie Turner <charlie.turner@arm.com>2015-09-24 10:24:58 +0000
commit2720593ab4518012af619c90b45f60ccc4ae4f29 (patch)
tree14d05e335eb725c957e3b3abf7fa362276ea4723 /llvm
parente0395a7f7f3a0ba22080fe27016702a72de63ddb (diff)
downloadbcm5719-llvm-2720593ab4518012af619c90b45f60ccc4ae4f29.tar.gz
bcm5719-llvm-2720593ab4518012af619c90b45f60ccc4ae4f29.zip
[InstCombine] Recognize another bswap idiom.
Summary: The byte-swap recognizer can now notice that this ``` uint32_t bswap(uint32_t x) { x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16; x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8; return x; } ``` is a bswap. Fixes PR23863. Reviewers: nlewycky, hfinkel, hans, jmolloy, rengolin Subscribers: majnemer, rengolin, llvm-commits Differential Revision: http://reviews.llvm.org/D12637 llvm-svn: 248482
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp14
-rw-r--r--llvm/test/Transforms/InstCombine/bswap.ll14
2 files changed, 22 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 0a603c030d9..5459c8955a1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2220,14 +2220,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
ConstantInt *C1 = nullptr, *C2 = nullptr;
// (A | B) | C and A | (B | C) -> bswap if possible.
+ bool OrOfOrs = match(Op0, m_Or(m_Value(), m_Value())) ||
+ match(Op1, m_Or(m_Value(), m_Value()));
// (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
- if (match(Op0, m_Or(m_Value(), m_Value())) ||
- match(Op1, m_Or(m_Value(), m_Value())) ||
- (match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
- match(Op1, m_LogicalShift(m_Value(), m_Value())))) {
+ bool OrOfShifts = match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
+ match(Op1, m_LogicalShift(m_Value(), m_Value()));
+ // (A & B) | (C & D) -> bswap if possible.
+ bool OrOfAnds = match(Op0, m_And(m_Value(), m_Value())) &&
+ match(Op1, m_And(m_Value(), m_Value()));
+
+ if (OrOfOrs || OrOfShifts || OrOfAnds)
if (Instruction *BSwap = MatchBSwap(I))
return BSwap;
- }
// (X^C)|Y -> (X|Y)^C iff Y&C == 0
if (Op0->hasOneUse() &&
diff --git a/llvm/test/Transforms/InstCombine/bswap.ll b/llvm/test/Transforms/InstCombine/bswap.ll
index ba7df3125f4..b48b2a57c8c 100644
--- a/llvm/test/Transforms/InstCombine/bswap.ll
+++ b/llvm/test/Transforms/InstCombine/bswap.ll
@@ -1,7 +1,7 @@
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
; RUN: opt < %s -instcombine -S | \
-; RUN: grep "call.*llvm.bswap" | count 6
+; RUN: grep "call.*llvm.bswap" | count 7
define i32 @test1(i32 %i) {
%tmp1 = lshr i32 %i, 24 ; <i32> [#uses=1]
@@ -72,3 +72,15 @@ define i32 @test6(i32 %x) nounwind readnone {
ret i32 %tmp7
}
+; PR23863
+define i32 @test7(i32 %x) {
+ %shl = shl i32 %x, 16
+ %shr = lshr i32 %x, 16
+ %or = or i32 %shl, %shr
+ %and2 = shl i32 %or, 8
+ %shl3 = and i32 %and2, -16711936
+ %and4 = lshr i32 %or, 8
+ %shr5 = and i32 %and4, 16711935
+ %or6 = or i32 %shl3, %shr5
+ ret i32 %or6
+}
OpenPOWER on IntegriCloud