Skip to content

Commit

Permalink
[SLSR] handle (B | i) * S
Browse files Browse the repository at this point in the history
Summary:
Consider (B | i) * S as (B + i) * S if B and i have no bits set in
common.

Test Plan: @or in slsr-mul.ll

Reviewers: broune, meheff

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D9788

llvm-svn: 237456
  • Loading branch information
Jingyue Wu committed May 15, 2015
1 parent cfb0443 commit 80a96d2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
24 changes: 21 additions & 3 deletions llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -404,20 +405,37 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd(
}
}

// 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<IntegerType>(I->getType()), 0);
allocateCandidatesAndFindBasis(Candidate::Mul, SE->getSCEV(LHS), Zero, RHS,
I);
I);
}
}

Expand Down
23 changes: 23 additions & 0 deletions llvm/test/Transforms/StraightLineStrengthReduce/slsr-mul.ll
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,29 @@ define void @non_canonicalized(i32 %b, i32 %s) {
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))
Expand Down

0 comments on commit 80a96d2

Please sign in to comment.