Skip to content

Commit 6bfe536

Browse files
committed
[InstCombine] add helper function for extract of with-overflow-intrinsic; NFC
We can do more with these patterns, so this block is going to grow.
1 parent 56a1c61 commit 6bfe536

File tree

2 files changed

+64
-50
lines changed

2 files changed

+64
-50
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
366366
Value *matchSelectFromAndOr(Value *A, Value *B, Value *C, Value *D);
367367
Value *getSelectCondition(Value *A, Value *B);
368368

369+
Instruction *foldExtractOfOverflowIntrinsic(ExtractValueInst &EV);
369370
Instruction *foldIntrinsicWithOverflowCommon(IntrinsicInst *II);
370371
Instruction *foldFPSignBitOps(BinaryOperator &I);
371372

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,6 +3247,64 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
32473247
return nullptr;
32483248
}
32493249

3250+
Instruction *
3251+
InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) {
3252+
auto *WO = dyn_cast<WithOverflowInst>(EV.getAggregateOperand());
3253+
if (!WO)
3254+
return nullptr;
3255+
3256+
// extractvalue (any_mul_with_overflow X, -1), 0 --> -X
3257+
Intrinsic::ID OvID = WO->getIntrinsicID();
3258+
if (*EV.idx_begin() == 0 &&
3259+
(OvID == Intrinsic::smul_with_overflow ||
3260+
OvID == Intrinsic::umul_with_overflow) &&
3261+
match(WO->getArgOperand(1), m_AllOnes())) {
3262+
return BinaryOperator::CreateNeg(WO->getArgOperand(0));
3263+
}
3264+
3265+
// We're extracting from an overflow intrinsic. See if we're the only user.
3266+
// That allows us to simplify multiple result intrinsics to simpler things
3267+
// that just get one value.
3268+
if (!WO->hasOneUse())
3269+
return nullptr;
3270+
3271+
// Check if we're grabbing only the result of a 'with overflow' intrinsic
3272+
// and replace it with a traditional binary instruction.
3273+
if (*EV.idx_begin() == 0) {
3274+
Instruction::BinaryOps BinOp = WO->getBinaryOp();
3275+
Value *LHS = WO->getLHS(), *RHS = WO->getRHS();
3276+
// Replace the old instruction's uses with poison.
3277+
replaceInstUsesWith(*WO, PoisonValue::get(WO->getType()));
3278+
eraseInstFromFunction(*WO);
3279+
return BinaryOperator::Create(BinOp, LHS, RHS);
3280+
}
3281+
3282+
assert(*EV.idx_begin() == 1 && "Unexpected extract index for overflow inst");
3283+
3284+
// If only the overflow result is used, and the right hand side is a
3285+
// constant (or constant splat), we can remove the intrinsic by directly
3286+
// checking for overflow.
3287+
const APInt *C;
3288+
if (match(WO->getRHS(), m_APInt(C))) {
3289+
// Compute the no-wrap range for LHS given RHS=C, then construct an
3290+
// equivalent icmp, potentially using an offset.
3291+
ConstantRange NWR = ConstantRange::makeExactNoWrapRegion(
3292+
WO->getBinaryOp(), *C, WO->getNoWrapKind());
3293+
3294+
CmpInst::Predicate Pred;
3295+
APInt NewRHSC, Offset;
3296+
NWR.getEquivalentICmp(Pred, NewRHSC, Offset);
3297+
auto *OpTy = WO->getRHS()->getType();
3298+
auto *NewLHS = WO->getLHS();
3299+
if (Offset != 0)
3300+
NewLHS = Builder.CreateAdd(NewLHS, ConstantInt::get(OpTy, Offset));
3301+
return new ICmpInst(ICmpInst::getInversePredicate(Pred), NewLHS,
3302+
ConstantInt::get(OpTy, NewRHSC));
3303+
}
3304+
3305+
return nullptr;
3306+
}
3307+
32503308
Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
32513309
Value *Agg = EV.getAggregateOperand();
32523310

@@ -3308,58 +3366,11 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
33083366
return ExtractValueInst::Create(IV->getInsertedValueOperand(),
33093367
makeArrayRef(exti, exte));
33103368
}
3311-
if (WithOverflowInst *WO = dyn_cast<WithOverflowInst>(Agg)) {
3312-
// extractvalue (any_mul_with_overflow X, -1), 0 --> -X
3313-
Intrinsic::ID OvID = WO->getIntrinsicID();
3314-
if (*EV.idx_begin() == 0 &&
3315-
(OvID == Intrinsic::smul_with_overflow ||
3316-
OvID == Intrinsic::umul_with_overflow) &&
3317-
match(WO->getArgOperand(1), m_AllOnes())) {
3318-
return BinaryOperator::CreateNeg(WO->getArgOperand(0));
3319-
}
33203369

3321-
// We're extracting from an overflow intrinsic, see if we're the only user,
3322-
// which allows us to simplify multiple result intrinsics to simpler
3323-
// things that just get one value.
3324-
if (WO->hasOneUse()) {
3325-
// Check if we're grabbing only the result of a 'with overflow' intrinsic
3326-
// and replace it with a traditional binary instruction.
3327-
if (*EV.idx_begin() == 0) {
3328-
Instruction::BinaryOps BinOp = WO->getBinaryOp();
3329-
Value *LHS = WO->getLHS(), *RHS = WO->getRHS();
3330-
// Replace the old instruction's uses with poison.
3331-
replaceInstUsesWith(*WO, PoisonValue::get(WO->getType()));
3332-
eraseInstFromFunction(*WO);
3333-
return BinaryOperator::Create(BinOp, LHS, RHS);
3334-
}
3370+
if (Instruction *R = foldExtractOfOverflowIntrinsic(EV))
3371+
return R;
33353372

3336-
assert(*EV.idx_begin() == 1 &&
3337-
"unexpected extract index for overflow inst");
3338-
3339-
// If only the overflow result is used, and the right hand side is a
3340-
// constant (or constant splat), we can remove the intrinsic by directly
3341-
// checking for overflow.
3342-
const APInt *C;
3343-
if (match(WO->getRHS(), m_APInt(C))) {
3344-
// Compute the no-wrap range for LHS given RHS=C, then construct an
3345-
// equivalent icmp, potentially using an offset.
3346-
ConstantRange NWR =
3347-
ConstantRange::makeExactNoWrapRegion(WO->getBinaryOp(), *C,
3348-
WO->getNoWrapKind());
3349-
3350-
CmpInst::Predicate Pred;
3351-
APInt NewRHSC, Offset;
3352-
NWR.getEquivalentICmp(Pred, NewRHSC, Offset);
3353-
auto *OpTy = WO->getRHS()->getType();
3354-
auto *NewLHS = WO->getLHS();
3355-
if (Offset != 0)
3356-
NewLHS = Builder.CreateAdd(NewLHS, ConstantInt::get(OpTy, Offset));
3357-
return new ICmpInst(ICmpInst::getInversePredicate(Pred), NewLHS,
3358-
ConstantInt::get(OpTy, NewRHSC));
3359-
}
3360-
}
3361-
}
3362-
if (LoadInst *L = dyn_cast<LoadInst>(Agg))
3373+
if (LoadInst *L = dyn_cast<LoadInst>(Agg)) {
33633374
// If the (non-volatile) load only has one use, we can rewrite this to a
33643375
// load from a GEP. This reduces the size of the load. If a load is used
33653376
// only by extractvalue instructions then this either must have been
@@ -3386,6 +3397,8 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
33863397
// the wrong spot, so use replaceInstUsesWith().
33873398
return replaceInstUsesWith(EV, NL);
33883399
}
3400+
}
3401+
33893402
// We could simplify extracts from other values. Note that nested extracts may
33903403
// already be simplified implicitly by the above: extract (extract (insert) )
33913404
// will be translated into extract ( insert ( extract ) ) first and then just

0 commit comments

Comments
 (0)