mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-11 07:15:26 +00:00
Teach CorrelatedValuePropagation to mark adds as no wrap
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277592 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
48f2d1dea0
commit
5267dec504
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/Analysis/InstructionSimplify.h"
|
#include "llvm/Analysis/InstructionSimplify.h"
|
||||||
#include "llvm/Analysis/LazyValueInfo.h"
|
#include "llvm/Analysis/LazyValueInfo.h"
|
||||||
#include "llvm/IR/CFG.h"
|
#include "llvm/IR/CFG.h"
|
||||||
|
#include "llvm/IR/ConstantRange.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
@ -381,6 +382,59 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
|||||||
return true;
|
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) {
|
static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
|
||||||
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
|
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
|
||||||
return C;
|
return C;
|
||||||
@ -436,6 +490,9 @@ static bool runImpl(Function &F, LazyValueInfo *LVI) {
|
|||||||
case Instruction::SDiv:
|
case Instruction::SDiv:
|
||||||
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
|
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
|
||||||
break;
|
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