mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Teach CorrelatedValuePropagation to mark adds as no wrap
This is a resubmission of previously reverted r277592. It was hitting overly strong assertion in getConstantRange which was relaxed in r278217. Use LVI to prove that adds do not wrap. The change is motivated by https://llvm.org/bugs/show_bug.cgi?id=28620 bug and it's the first step to fix that problem. Reviewed By: sanjoy Differential Revision: http://reviews.llvm.org/D23059 llvm-svn: 278220
This commit is contained in:
parent
c0a2a41fc2
commit
062c0daef0
@ -18,6 +18,7 @@
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LazyValueInfo.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
@ -381,6 +382,59 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
|
||||
typedef OverflowingBinaryOperator OBO;
|
||||
|
||||
if (AddOp->getType()->isVectorTy() || hasLocalDefs(AddOp))
|
||||
return false;
|
||||
|
||||
bool NSW = AddOp->hasNoSignedWrap();
|
||||
bool NUW = AddOp->hasNoUnsignedWrap();
|
||||
if (NSW && NUW)
|
||||
return false;
|
||||
|
||||
BasicBlock *BB = AddOp->getParent();
|
||||
|
||||
Value *LHS = AddOp->getOperand(0);
|
||||
Value *RHS = AddOp->getOperand(1);
|
||||
|
||||
ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp);
|
||||
|
||||
// Initialize RRange only if we need it. If we know that guaranteed no wrap
|
||||
// range for the given LHS range is empty don't spend time calculating the
|
||||
// range for the RHS.
|
||||
Optional<ConstantRange> RRange;
|
||||
auto LazyRRange = [&] () {
|
||||
if (!RRange)
|
||||
RRange = LVI->getConstantRange(RHS, BB, AddOp);
|
||||
return RRange.getValue();
|
||||
};
|
||||
|
||||
bool Changed = false;
|
||||
if (!NUW) {
|
||||
ConstantRange NUWRange =
|
||||
LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
|
||||
OBO::NoUnsignedWrap);
|
||||
if (!NUWRange.isEmptySet()) {
|
||||
bool NewNUW = NUWRange.contains(LazyRRange());
|
||||
AddOp->setHasNoUnsignedWrap(NewNUW);
|
||||
Changed |= NewNUW;
|
||||
}
|
||||
}
|
||||
if (!NSW) {
|
||||
ConstantRange NSWRange =
|
||||
LRange.makeGuaranteedNoWrapRegion(BinaryOperator::Add, LRange,
|
||||
OBO::NoSignedWrap);
|
||||
if (!NSWRange.isEmptySet()) {
|
||||
bool NewNSW = NSWRange.contains(LazyRRange());
|
||||
AddOp->setHasNoSignedWrap(NewNSW);
|
||||
Changed |= NewNSW;
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
|
||||
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
|
||||
return C;
|
||||
@ -436,6 +490,9 @@ static bool runImpl(Function &F, LazyValueInfo *LVI) {
|
||||
case Instruction::SDiv:
|
||||
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
|
||||
break;
|
||||
case Instruction::Add:
|
||||
BBChanged |= processAdd(cast<BinaryOperator>(II), LVI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
91
test/Transforms/CorrelatedValuePropagation/add.ll
Normal file
91
test/Transforms/CorrelatedValuePropagation/add.ll
Normal file
@ -0,0 +1,91 @@
|
||||
; RUN: opt < %s -correlated-propagation -S | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: @test0(
|
||||
define void @test0(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp slt i32 %a, 100
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add nsw i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test1(
|
||||
define void @test1(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp ult i32 %a, 100
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add nuw nsw i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test2(
|
||||
define void @test2(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp ult i32 %a, -1
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add nuw i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test3(
|
||||
define void @test3(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp ule i32 %a, -1
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test4(
|
||||
define void @test4(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp slt i32 %a, 2147483647
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add nsw i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @test5(
|
||||
define void @test5(i32 %a) {
|
||||
entry:
|
||||
%cmp = icmp sle i32 %a, 2147483647
|
||||
br i1 %cmp, label %bb, label %exit
|
||||
|
||||
bb:
|
||||
; CHECK: %add = add i32 %a, 1
|
||||
%add = add i32 %a, 1
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user