Skip to content

Commit

Permalink
[SCEV] Make SCEV or modeling more aggressive.
Browse files Browse the repository at this point in the history
Use haveNoCommonBitsSet to figure out whether an "or" instruction
is equivalent to addition. This handles more cases than just
checking for a constant on the RHS.

Differential Revision: https://reviews.llvm.org/D32239

llvm-svn: 300746
  • Loading branch information
Eli Friedman committed Apr 19, 2017
1 parent b45905c commit e77d2b8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 22 deletions.
28 changes: 6 additions & 22 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Expand Up @@ -5328,28 +5328,12 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
break;

case Instruction::Or:
// If the RHS of the Or is a constant, we may have something like:
// X*4+1 which got turned into X*4|1. Handle this as an Add so loop
// optimizations will transparently handle this case.
//
// In order for this transformation to be safe, the LHS must be of the
// form X*(2^n) and the Or constant must be less than 2^n.
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->RHS)) {
const SCEV *LHS = getSCEV(BO->LHS);
const APInt &CIVal = CI->getValue();
if (GetMinTrailingZeros(LHS) >=
(CIVal.getBitWidth() - CIVal.countLeadingZeros())) {
// Build a plain add SCEV.
const SCEV *S = getAddExpr(LHS, getSCEV(CI));
// If the LHS of the add was an addrec and it has no-wrap flags,
// transfer the no-wrap flags, since an or won't introduce a wrap.
if (const SCEVAddRecExpr *NewAR = dyn_cast<SCEVAddRecExpr>(S)) {
const SCEVAddRecExpr *OldAR = cast<SCEVAddRecExpr>(LHS);
const_cast<SCEVAddRecExpr *>(NewAR)->setNoWrapFlags(
OldAR->getNoWrapFlags());
}
return S;
}
// Use ValueTracking to check whether this is actually an add.
if (haveNoCommonBitsSet(BO->LHS, BO->RHS, getDataLayout(), &AC,
nullptr, &DT)) {
// There aren't any common bits set, so the add can't wrap.
auto Flags = SCEV::NoWrapFlags(SCEV::FlagNUW | SCEV::FlagNSW);
return getAddExpr(getSCEV(BO->LHS), getSCEV(BO->RHS), Flags);
}
break;

Expand Down
38 changes: 38 additions & 0 deletions llvm/test/Analysis/ScalarEvolution/or-as-add.ll
@@ -0,0 +1,38 @@
; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s

declare void @z(i32)
declare void @z2(i64)

define void @fun(i1 %bool, i32 %x) {
entry:
br label %body
body:
%i = phi i32 [ 0, %entry ], [ %i.next, %body ]
%bottom_zero = mul i32 %i, 2
%a = or i32 %bottom_zero, 1
call void @z(i32 %a)
%bool_ext = zext i1 %bool to i32
%b = or i32 %bool_ext, %bottom_zero
call void @z(i32 %b)
%shifted = lshr i32 %x, 31
%c = or i32 %shifted, %bottom_zero
call void @z(i32 %c)
%i_ext = zext i32 %i to i64
%d = or i64 %i_ext, 4294967296
call void @z2(i64 %d)
%i.next = add i32 %i, 1
%cond = icmp eq i32 %i.next, 10
br i1 %cond, label %exit, label %body
exit:
ret void
}

; CHECK: %a = or i32 %bottom_zero, 1
; CHECK-NEXT: --> {1,+,2}<%body>
; CHECK: %b = or i32 %bool_ext, %bottom_zero
; CHECK-NEXT: --> {(zext i1 %bool to i32),+,2}
; CHECK: %c = or i32 %shifted, %bottom_zero
; CHECK-NEXT: --> {(%x /u -2147483648),+,2}<%body>
; CHECK: %d = or i64 %i_ext, 4294967296
; CHECK-NEXT: --> {4294967296,+,1}<nuw><nsw><%body>

0 comments on commit e77d2b8

Please sign in to comment.