Index: lib/Transforms/Scalar/StraightLineStrengthReduce.cpp =================================================================== --- lib/Transforms/Scalar/StraightLineStrengthReduce.cpp +++ lib/Transforms/Scalar/StraightLineStrengthReduce.cpp @@ -61,6 +61,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" @@ -404,20 +405,37 @@ } } +// Returns true if A matches B + C where C is constant. +static bool matchesAdd(Value *A, Value *&B, ConstantInt *&C) { + return (match(A, m_Add(m_Value(B), m_ConstantInt(C))) || + match(A, m_Add(m_ConstantInt(C), m_Value(B)))); +} + +// Returns true if A matches B | C where C is constant. +static bool matchesOr(Value *A, Value *&B, ConstantInt *&C) { + return (match(A, m_Or(m_Value(B), m_ConstantInt(C))) || + match(A, m_Or(m_ConstantInt(C), m_Value(B)))); +} + void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForMul( Value *LHS, Value *RHS, Instruction *I) { Value *B = nullptr; ConstantInt *Idx = nullptr; - if (match(LHS, m_Add(m_Value(B), m_ConstantInt(Idx))) || - match(LHS, m_Add(m_ConstantInt(Idx), m_Value(B)))) { + if (matchesAdd(LHS, B, Idx)) { // If LHS is in the form of "Base + Index", then I is in the form of // "(Base + Index) * RHS". allocateCandidatesAndFindBasis(Candidate::Mul, SE->getSCEV(B), Idx, RHS, I); + } else if (matchesOr(LHS, B, Idx) && haveNoCommonBitsSet(B, Idx, *DL)) { + // If LHS is in the form of "Base | Index" and Base and Index have no common + // bits set, then + // Base | Index = Base + Index + // and I is thus in the form of "(Base + Index) * RHS". + allocateCandidatesAndFindBasis(Candidate::Mul, SE->getSCEV(B), Idx, RHS, I); } else { // Otherwise, at least try the form (LHS + 0) * RHS. ConstantInt *Zero = ConstantInt::get(cast(I->getType()), 0); allocateCandidatesAndFindBasis(Candidate::Mul, SE->getSCEV(LHS), Zero, RHS, - I); + I); } } Index: test/Transforms/StraightLineStrengthReduce/slsr-mul.ll =================================================================== --- test/Transforms/StraightLineStrengthReduce/slsr-mul.ll +++ test/Transforms/StraightLineStrengthReduce/slsr-mul.ll @@ -44,6 +44,29 @@ ret void } +define void @or(i32 %a, i32 %s) { + %b = shl i32 %a, 1 +; CHECK-LABEL: @or( + ; foo(b * s); + %mul0 = mul i32 %b, %s +; CHECK: [[base:[^ ]+]] = mul i32 + call void @foo(i32 %mul0) + + ; foo((b | 1) * s); + %b1 = or i32 %b, 1 + %mul1 = mul i32 %b1, %s +; CHECK: add i32 [[base]], %s + call void @foo(i32 %mul1) + + ; foo((b | 2) * s); + %b2 = or i32 %b, 2 + %mul2 = mul i32 %b2, %s +; CHECK: mul i32 %b2, %s + call void @foo(i32 %mul2) + + ret void +} + ; foo(a * b) ; foo((a + 1) * b) ; foo(a * (b + 1))