[llvm] ff218cb - [InstSimplify] Fold degenerate abs of abs form

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 8 08:59:22 PDT 2020


Given:

x == 0 ? -abs(x) : Y

We should really be producing:

x == 0 ? 0 : Y

This seems like something CVP might be able to handle, or even an 
alternate instcombine rule.

And once we have

x == 0 ? 0 : abs(x)

We should definitely fold that to abs(x).

Not suggesting that your change needs removed; just that there's an 
alternate, slightly more general way of achieving the same thing.

Philip


On 9/6/20 12:45 AM, Nikita Popov via llvm-commits wrote:
> Author: Nikita Popov
> Date: 2020-09-06T09:43:08+02:00
> New Revision: ff218cbc84ff3783cb5ad030397adef8c9e8d444
>
> URL: https://github.com/llvm/llvm-project/commit/ff218cbc84ff3783cb5ad030397adef8c9e8d444
> DIFF: https://github.com/llvm/llvm-project/commit/ff218cbc84ff3783cb5ad030397adef8c9e8d444.diff
>
> LOG: [InstSimplify] Fold degenerate abs of abs form
>
> This addresses the remaining issue from D87188. Due to a series of
> folds, we may end up with abs-of-abs represented as
> x == 0 ? -abs(x) : abs(x). Rather than recognizing this as a special
> abs pattern and doing an abs-of-abs fold on it afterwards,
> I'm directly folding this to one of the select operands in InstSimplify.
>
> The general pattern falls into the "select with operand replaced"
> category, but that fold is not powerful enough to recognize that
> both hands of the select are the same for value zero.
>
> Differential Revision: https://reviews.llvm.org/D87197
>
> Added:
>      
>
> Modified:
>      llvm/lib/Analysis/InstructionSimplify.cpp
>      llvm/test/Transforms/InstSimplify/abs_intrinsic.ll
>
> Removed:
>      
>
>
> ################################################################################
> diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
> index 3139b5a96b27..7c13b41bc7e6 100644
> --- a/llvm/lib/Analysis/InstructionSimplify.cpp
> +++ b/llvm/lib/Analysis/InstructionSimplify.cpp
> @@ -3965,6 +3965,15 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
>       if (match(FalseVal, isRotate) && TrueVal == X && CmpLHS == ShAmt &&
>           Pred == ICmpInst::ICMP_EQ)
>         return FalseVal;
> +
> +    // X == 0 ? abs(X) : -abs(X) --> -abs(X)
> +    // X == 0 ? -abs(X) : abs(X) --> abs(X)
> +    if (match(TrueVal, m_Intrinsic<Intrinsic::abs>(m_Value(X))) &&
> +        match(FalseVal, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Specific(X)))))
> +      return FalseVal;
> +    if (match(TrueVal, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Value(X)))) &&
> +        match(FalseVal, m_Intrinsic<Intrinsic::abs>(m_Specific(X))))
> +      return FalseVal;
>     }
>   
>     // Check for other compares that behave like bit test.
>
> diff  --git a/llvm/test/Transforms/InstSimplify/abs_intrinsic.ll b/llvm/test/Transforms/InstSimplify/abs_intrinsic.ll
> index e9305a927c42..70b50da9f041 100644
> --- a/llvm/test/Transforms/InstSimplify/abs_intrinsic.ll
> +++ b/llvm/test/Transforms/InstSimplify/abs_intrinsic.ll
> @@ -205,10 +205,7 @@ define i1 @abs_ule_int_min(i8 %x) {
>   define i32 @select_abs_of_abs_eq(i32 %x) {
>   ; CHECK-LABEL: @select_abs_of_abs_eq(
>   ; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
> -; CHECK-NEXT:    [[NEG:%.*]] = sub i32 0, [[ABS]]
> -; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X]], 0
> -; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[ABS]]
> -; CHECK-NEXT:    ret i32 [[SEL]]
> +; CHECK-NEXT:    ret i32 [[ABS]]
>   ;
>     %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
>     %neg = sub i32 0, %abs
> @@ -220,10 +217,7 @@ define i32 @select_abs_of_abs_eq(i32 %x) {
>   define i32 @select_abs_of_abs_ne(i32 %x) {
>   ; CHECK-LABEL: @select_abs_of_abs_ne(
>   ; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
> -; CHECK-NEXT:    [[NEG:%.*]] = sub i32 0, [[ABS]]
> -; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X]], 0
> -; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[ABS]], i32 [[NEG]]
> -; CHECK-NEXT:    ret i32 [[SEL]]
> +; CHECK-NEXT:    ret i32 [[ABS]]
>   ;
>     %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
>     %neg = sub i32 0, %abs
> @@ -236,9 +230,7 @@ define i32 @select_nabs_of_abs_eq(i32 %x) {
>   ; CHECK-LABEL: @select_nabs_of_abs_eq(
>   ; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
>   ; CHECK-NEXT:    [[NEG:%.*]] = sub i32 0, [[ABS]]
> -; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X]], 0
> -; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[ABS]], i32 [[NEG]]
> -; CHECK-NEXT:    ret i32 [[SEL]]
> +; CHECK-NEXT:    ret i32 [[NEG]]
>   ;
>     %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
>     %neg = sub i32 0, %abs
> @@ -251,9 +243,7 @@ define i32 @select_nabs_of_abs_ne(i32 %x) {
>   ; CHECK-LABEL: @select_nabs_of_abs_ne(
>   ; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
>   ; CHECK-NEXT:    [[NEG:%.*]] = sub i32 0, [[ABS]]
> -; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X]], 0
> -; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[ABS]]
> -; CHECK-NEXT:    ret i32 [[SEL]]
> +; CHECK-NEXT:    ret i32 [[NEG]]
>   ;
>     %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
>     %neg = sub i32 0, %abs
>
>
>          
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list