[llvm] [Instcombine]: Folds`llvm.ucmp` and `llvm.scmp` (PR #168505)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 28 08:42:20 PST 2025
nikic wrote:
> > The remaining transform here looks like something that the select equivalence class of transforms should handle. I think the reason it doesn't is potential derefinement, which requires adding these intrinsics as a special case in
>
> hmmm Putting it into `simplifyWithOpsReplaced` requires a bit of refactoring and double checking.
>
> At the moment, `simplifyWithOpsReplaced` is only called in `simplifySelectWithEquivalence`. `simplifySelectWithEquivalence` only replaces an instruction when both simplified true and simplified false return the same value. However, that's not true for that transformation. The simplified true val must be a constant and I would need to double check whether the simplified false val is an intrinsic. Something that I would have already done in `simplifyWithOpsReplaced` (hence double checking).
>
> https://github.com/llvm/llvm-project/blob/8290134a7421c5a5ce3348b29f908887158b4b8a/llvm/lib/Analysis/InstructionSimplify.cpp#L4690
>
> In the latest commit, I added a method `simplifySelectWhenValInstrinsic` that tries to fold the computation after the existing implementation is done.
I don't really follow. The pattern you have is `x == y ? 0 : ucmp(x, y)`, where under the replacement `y -> x` the RHS is `ucmp(x, x)` which is `0`, which is the same as the LHS. This is the condition under which the fold is performed. It just doesn't happened because (currently) we can't prove that replacing `0` with `ucmp(x, y)` in this case does not derefine.
> > Something to watch out for are poison-generating attributes on the call. I believe your current implementation is also not strictly correct in that regard (e.g. imagine that there's a range(1, 2) attribute on the return value, but after the transform a return of 0 is also valid.)
>
> Could you give me an example where this range attribute could be put? I tried the snippet below but `opt` is correcting the range for me automatically.
>
> Input:
>
> ```
> ; HERE is the range updated
> declare range(i32 1, 2) i32 @llvm.ucmp.i32.i32(i32, i32) #0
>
> define i32 @fold_ucmp(i32 %0, i32 %1) {
> %3 = icmp eq i32 %0, %1
> %4 = tail call i32 @llvm.ucmp.i32.i32(i32 %0, i32 %1)
> %5 = select i1 %3, i32 0, i32 %4
> ret i32 %5
> }
> ```
The range attribtue can be placed on the call-site. You can have something like `call range(1, 2) i32 @llvm.ucmp.i32.i32(i32 %0, i32 %1)`, though it is contrived.
https://github.com/llvm/llvm-project/pull/168505
More information about the llvm-commits
mailing list