[llvm] [InstCombine] Fold trunc(umin/umax(zext(x), y & mask)) to narrower umin/umax (PR #173221)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 27 03:13:10 PST 2025
================
@@ -607,6 +623,32 @@ bool TypeEvaluationHelper::canEvaluateTruncatedPred(Value *V, Type *Ty,
return canEvaluateTruncatedImpl(I->getOperand(0), Ty, IC, CxtI) &&
canEvaluateTruncatedImpl(I->getOperand(1), Ty, IC, CxtI);
+ case Instruction::Call:
+ if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::umax:
+ case Intrinsic::umin: {
+ unsigned OrginalBitWidth = OrigTy->getScalarSizeInBits();
+ unsigned TargetBitWidth = Ty->getScalarSizeInBits();
+ assert(TargetBitWidth < OrginalBitWidth && "Unexpected bitwidths!");
+ APInt Mask = APInt::getBitsSetFrom(OrginalBitWidth, TargetBitWidth);
+ // If we know that all operands is always within the truncated
+ // range, we can perform the umin in the smaller type.
+ if (IC.MaskedValueIsZero(II->getArgOperand(0), Mask, CxtI) &&
+ IC.MaskedValueIsZero(II->getArgOperand(1), Mask, CxtI)) {
+ Value *Op0 = II->getArgOperand(0);
+ Value *Op1 = II->getArgOperand(1);
+ return canEvaluateTruncatedImpl(Op0, Ty, IC, CxtI) ||
----------------
nikic wrote:
Okay, I think I get what you're trying to do here. The existing approach of this code is to only allow pushing the truncate upwards if all operands can be optimized, not if we still have to truncate one of them.
I'd suggest to start by just handling the base pattern of:
```
define i16 @test(i16 %a1, i16 %a2) {
%a1.ext = zext i16 %a1 to i32
%a2.ext = zext i16 %a2 to i32
call void @use(i32 %a1.ext)
call void @use(i32 %a2.ext)
%min = call i32 @llvm.umin.i32(i32 %a1.ext, i32 %a2.ext)
%res = trunc i32 %min to i16
ret i16 %res
}
declare void @use(i32)
```
The extra uses here are to prevent other folds from doing the same thing via other pathways.
Then as a second step, we can specially handle the case of "one-use and by the bit width mask", which is the case where we can convert the and into a trunc.
The alternative extension for the second step would be to generally allow pushing truncs upward as long as we have to insert at most one new trunc, but that would be a more significant change.
https://github.com/llvm/llvm-project/pull/173221
More information about the llvm-commits
mailing list