[llvm] [InstCombine] Detect uadd with overflow idiom (PR #140178)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri May 30 11:39:53 PDT 2025
================
@@ -6622,38 +6626,42 @@ static Instruction *processUMulZExtIdiom(ICmpInst &I, Value *MulVal,
}
InstCombiner::BuilderTy &Builder = IC.Builder;
- Builder.SetInsertPoint(MulInstr);
-
- // Replace: mul(zext A, zext B) --> mul.with.overflow(A, B)
- Value *MulA = A, *MulB = B;
- if (WidthA < MulWidth)
- MulA = Builder.CreateZExt(A, MulType);
- if (WidthB < MulWidth)
- MulB = Builder.CreateZExt(B, MulType);
- CallInst *Call =
- Builder.CreateIntrinsic(Intrinsic::umul_with_overflow, MulType,
- {MulA, MulB}, /*FMFSource=*/nullptr, "umul");
- IC.addToWorklist(MulInstr);
-
- // If there are uses of mul result other than the comparison, we know that
+ Builder.SetInsertPoint(Instr);
+
+ // Replace: add/mul(zext A, zext B) --> add/mul.with.overflow(A, B)
+ Value *ResultA = A, *ResultB = B;
+ if (WidthA < ResultWidth)
+ ResultA = Builder.CreateZExt(A, ResultType);
+ if (WidthB < ResultWidth)
+ ResultB = Builder.CreateZExt(B, ResultType);
+ CallInst *Call = Builder.CreateIntrinsic(
+ Opcode == Instruction::Add ? Intrinsic::uadd_with_overflow
+ : Intrinsic::umul_with_overflow,
+ ResultType, {ResultA, ResultB}, /*FMFSource=*/nullptr,
+ Opcode == Instruction::Add ? "uadd" : "umul");
+ IC.addToWorklist(Instr);
+
+ // If there are uses of add result other than the comparison, we know that
// they are truncation or binary AND. Change them to use result of
- // mul.with.overflow and adjust properly mask/size.
- if (MulVal->hasNUsesOrMore(2)) {
- Value *Mul = Builder.CreateExtractValue(Call, 0, "umul.value");
- for (User *U : make_early_inc_range(MulVal->users())) {
+ // add/mul.with.overflow and adjust properly mask/size.
+ if (Val->hasNUsesOrMore(2)) {
+ Value *Extract = Builder.CreateExtractValue(
+ Call, 0, Opcode == Instruction::Add ? "uadd.value" : "umul.value");
+ for (User *U : make_early_inc_range(Val->users())) {
if (U == &I)
continue;
if (TruncInst *TI = dyn_cast<TruncInst>(U)) {
- if (TI->getType()->getPrimitiveSizeInBits() == MulWidth)
- IC.replaceInstUsesWith(*TI, Mul);
+ if (TI->getType()->getPrimitiveSizeInBits() == ResultWidth)
+ IC.replaceInstUsesWith(*TI, Extract);
else
- TI->setOperand(0, Mul);
+ TI->setOperand(0, Extract);
} else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(U)) {
assert(BO->getOpcode() == Instruction::And);
----------------
topperc wrote:
I don't see any And in your test? Is there some other optimization that creates an And from your test?
https://github.com/llvm/llvm-project/pull/140178
More information about the llvm-commits
mailing list