forked from OSchip/llvm-project
have instcombine preserve nsw/nuw/exact when sinking
common operations through a phi. llvm-svn: 125790
This commit is contained in:
parent
99827e861f
commit
a8fed47eed
|
@ -31,22 +31,37 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
|
|||
const Type *LHSType = LHSVal->getType();
|
||||
const Type *RHSType = RHSVal->getType();
|
||||
|
||||
bool isNUW = false, isNSW = false, isExact = false;
|
||||
if (OverflowingBinaryOperator *BO =
|
||||
dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
|
||||
isNUW = BO->hasNoUnsignedWrap();
|
||||
isNSW = BO->hasNoSignedWrap();
|
||||
} else if (PossiblyExactOperator *PEO =
|
||||
dyn_cast<PossiblyExactOperator>(FirstInst))
|
||||
isExact = PEO->isExact();
|
||||
|
||||
// Scan to see if all operands are the same opcode, and all have one use.
|
||||
for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
|
||||
Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i));
|
||||
if (!I || I->getOpcode() != Opc || !I->hasOneUse() ||
|
||||
// Verify type of the LHS matches so we don't fold cmp's of different
|
||||
// types or GEP's with different index types.
|
||||
// types.
|
||||
I->getOperand(0)->getType() != LHSType ||
|
||||
I->getOperand(1)->getType() != RHSType)
|
||||
return 0;
|
||||
|
||||
// If they are CmpInst instructions, check their predicates
|
||||
if (Opc == Instruction::ICmp || Opc == Instruction::FCmp)
|
||||
if (cast<CmpInst>(I)->getPredicate() !=
|
||||
cast<CmpInst>(FirstInst)->getPredicate())
|
||||
if (CmpInst *CI = dyn_cast<CmpInst>(I))
|
||||
if (CI->getPredicate() != cast<CmpInst>(FirstInst)->getPredicate())
|
||||
return 0;
|
||||
|
||||
if (isNUW)
|
||||
isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
|
||||
if (isNSW)
|
||||
isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
|
||||
if (isExact)
|
||||
isExact = cast<PossiblyExactOperator>(I)->isExact();
|
||||
|
||||
// Keep track of which operand needs a phi node.
|
||||
if (I->getOperand(0) != LHSVal) LHSVal = 0;
|
||||
if (I->getOperand(1) != RHSVal) RHSVal = 0;
|
||||
|
@ -97,11 +112,17 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
|
|||
}
|
||||
}
|
||||
|
||||
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst))
|
||||
return BinaryOperator::Create(BinOp->getOpcode(), LHSVal, RHSVal);
|
||||
CmpInst *CIOp = cast<CmpInst>(FirstInst);
|
||||
return CmpInst::Create(CIOp->getOpcode(), CIOp->getPredicate(),
|
||||
LHSVal, RHSVal);
|
||||
if (CmpInst *CIOp = dyn_cast<CmpInst>(FirstInst))
|
||||
return CmpInst::Create(CIOp->getOpcode(), CIOp->getPredicate(),
|
||||
LHSVal, RHSVal);
|
||||
|
||||
BinaryOperator *BinOp = cast<BinaryOperator>(FirstInst);
|
||||
BinaryOperator *NewBinOp =
|
||||
BinaryOperator::Create(BinOp->getOpcode(), LHSVal, RHSVal);
|
||||
if (isNUW) NewBinOp->setHasNoUnsignedWrap();
|
||||
if (isNSW) NewBinOp->setHasNoSignedWrap();
|
||||
if (isExact) NewBinOp->setIsExact();
|
||||
return NewBinOp;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) {
|
||||
|
@ -373,6 +394,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
|
|||
// code size and simplifying code.
|
||||
Constant *ConstantOp = 0;
|
||||
const Type *CastSrcTy = 0;
|
||||
bool isNUW = false, isNSW = false, isExact = false;
|
||||
|
||||
if (isa<CastInst>(FirstInst)) {
|
||||
CastSrcTy = FirstInst->getOperand(0)->getType();
|
||||
|
@ -389,6 +411,14 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
|
|||
ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
|
||||
if (ConstantOp == 0)
|
||||
return FoldPHIArgBinOpIntoPHI(PN);
|
||||
|
||||
if (OverflowingBinaryOperator *BO =
|
||||
dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
|
||||
isNUW = BO->hasNoUnsignedWrap();
|
||||
isNSW = BO->hasNoSignedWrap();
|
||||
} else if (PossiblyExactOperator *PEO =
|
||||
dyn_cast<PossiblyExactOperator>(FirstInst))
|
||||
isExact = PEO->isExact();
|
||||
} else {
|
||||
return 0; // Cannot fold this operation.
|
||||
}
|
||||
|
@ -404,6 +434,13 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
|
|||
} else if (I->getOperand(1) != ConstantOp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isNUW)
|
||||
isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
|
||||
if (isNSW)
|
||||
isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
|
||||
if (isExact)
|
||||
isExact = cast<PossiblyExactOperator>(I)->isExact();
|
||||
}
|
||||
|
||||
// Okay, they are all the same operation. Create a new PHI node of the
|
||||
|
@ -438,8 +475,13 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
|
|||
if (CastInst *FirstCI = dyn_cast<CastInst>(FirstInst))
|
||||
return CastInst::Create(FirstCI->getOpcode(), PhiVal, PN.getType());
|
||||
|
||||
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst))
|
||||
return BinaryOperator::Create(BinOp->getOpcode(), PhiVal, ConstantOp);
|
||||
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst)) {
|
||||
BinOp = BinaryOperator::Create(BinOp->getOpcode(), PhiVal, ConstantOp);
|
||||
if (isNUW) BinOp->setHasNoUnsignedWrap();
|
||||
if (isNSW) BinOp->setHasNoSignedWrap();
|
||||
if (isExact) BinOp->setIsExact();
|
||||
return BinOp;
|
||||
}
|
||||
|
||||
CmpInst *CIOp = cast<CmpInst>(FirstInst);
|
||||
return CmpInst::Create(CIOp->getOpcode(), CIOp->getPredicate(),
|
||||
|
|
|
@ -526,3 +526,21 @@ Exit: ; preds = %Loop
|
|||
; CHECK-NEXT: ret i32 %B
|
||||
}
|
||||
|
||||
define i32 @test24(i32 %A, i1 %cond) {
|
||||
BB0:
|
||||
%X = add nuw nsw i32 %A, 1
|
||||
br i1 %cond, label %BB1, label %BB2
|
||||
|
||||
BB1:
|
||||
%Y = add nuw i32 %A, 1
|
||||
br label %BB2
|
||||
|
||||
BB2:
|
||||
%C = phi i32 [ %X, %BB0 ], [ %Y, %BB1 ]
|
||||
ret i32 %C
|
||||
; CHECK: @test24
|
||||
; CHECK-NOT: phi
|
||||
; CHECK: BB2:
|
||||
; CHECK-NEXT: %C = add nuw i32 %A, 1
|
||||
; CHECK-NEXT: ret i32 %C
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue