Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2220,14 +2220,18 @@ 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() && Index: test/Transforms/InstCombine/bswap.ll =================================================================== --- test/Transforms/InstCombine/bswap.ll +++ 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 ; [#uses=1] @@ -72,3 +72,15 @@ 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 +}