[llvm] 9020e22 - [InstCombine] Convert xor (ashr X, BW-1), C -> select(X >=s 0, C, ~C)

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 29 09:06:01 PDT 2021


David,

Not sure if you're interested, but it occurs to me that this can be 
generalized to any binop with the same structure.  We're basically just 
doing case analysis on the two possible results of the ashr and then 
forming a select by constant folding forward. That basic structure can 
apply to all bin ops.

e.g.

add (ashr X, BW-1), C
-->
select (x >= 0), C, C-1

We could even extend this to any two element range (say in CVP), though 
the profitability is a bit trickier there.

Philip

On 10/29/21 3:19 AM, David Green via llvm-commits wrote:
> Author: David Green
> Date: 2021-10-29T11:19:20+01:00
> New Revision: 9020e22a876e15afd7b5d13ac3abf180b5cf9343
>
> URL: https://github.com/llvm/llvm-project/commit/9020e22a876e15afd7b5d13ac3abf180b5cf9343
> DIFF: https://github.com/llvm/llvm-project/commit/9020e22a876e15afd7b5d13ac3abf180b5cf9343.diff
>
> LOG: [InstCombine] Convert xor (ashr X, BW-1), C -> select(X >=s 0, C, ~C)
>
> The sequence of instructions `xor (ashr X, BW-1), C` (or with a truncation
> `xor (trunc (ashr X, BW-1)), C)` takes a value, produces all zeros or all
> ones and with it optionally inverts a constant depending on whether the
> original input was positive or negative. This is the same as checking if
> the value is positive, and selecting between the constant and ~constant.
> https://alive2.llvm.org/ce/z/NJ85qY
>
> This is a fairly general version of a fold that helps pull saturating
> arithmetic into a canonical form.
>
> Differential Revision: https://reviews.llvm.org/D109151
>
> Added:
>      
>
> Modified:
>      llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
>      llvm/test/Transforms/InstCombine/truncating-saturate.ll
>      llvm/test/Transforms/InstCombine/xor-ashr.ll
>
> Removed:
>      
>
>
> ################################################################################
> diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> index ac79e21507c52..d8e8305ec8506 100644
> --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
> @@ -3569,10 +3569,10 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
>     if (Instruction *Xor = visitMaskedMerge(I, Builder))
>       return Xor;
>   
> -  // Use DeMorgan and reassociation to eliminate a 'not' op.
>     Value *X, *Y;
>     Constant *C1;
>     if (match(Op1, m_Constant(C1))) {
> +    // Use DeMorgan and reassociation to eliminate a 'not' op.
>       Constant *C2;
>       if (match(Op0, m_OneUse(m_Or(m_Not(m_Value(X)), m_Constant(C2))))) {
>         // (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
> @@ -3584,6 +3584,21 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
>         Value *Or = Builder.CreateOr(X, ConstantExpr::getNot(C2));
>         return BinaryOperator::CreateXor(Or, ConstantExpr::getNot(C1));
>       }
> +
> +    // Convert xor ([trunc] (ashr X, BW-1)), C =>
> +    //   select(X >s -1, C, ~C)
> +    // The ashr creates "AllZeroOrAllOne's", which then optionally inverses the
> +    // constant depending on whether this input is less than 0.
> +    const APInt *CA;
> +    if (match(Op0, m_OneUse(m_TruncOrSelf(
> +                       m_AShr(m_Value(X), m_APIntAllowUndef(CA))))) &&
> +        *CA == X->getType()->getScalarSizeInBits() - 1 &&
> +        !C1->isAllOnesValue()) {
> +      assert(!C1->isZeroValue() && "Unexpected xor with 0");
> +      Value *ICmp =
> +          Builder.CreateICmpSGT(X, Constant::getAllOnesValue(X->getType()));
> +      return SelectInst::Create(ICmp, Op1, Builder.CreateNot(Op1));
> +    }
>     }
>   
>     Type *Ty = I.getType();
>
> diff  --git a/llvm/test/Transforms/InstCombine/truncating-saturate.ll b/llvm/test/Transforms/InstCombine/truncating-saturate.ll
> index 7f8684df52e6a..154a69016f6ad 100644
> --- a/llvm/test/Transforms/InstCombine/truncating-saturate.ll
> +++ b/llvm/test/Transforms/InstCombine/truncating-saturate.ll
> @@ -13,9 +13,8 @@ define i8 @testi16i8(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -38,9 +37,8 @@ define i32 @testi64i32(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    ret i32 [[COND_I]]
>   ;
> @@ -155,9 +153,8 @@ define i32 @testi64i32addsat(i32 %a, i32 %b) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    ret i32 [[COND_I]]
>   ;
> @@ -183,9 +180,8 @@ define <4 x i8> @testv4i16i8(<4 x i16> %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc <4 x i16> [[ADD]] to <4 x i8>
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr <4 x i8> [[CONV1_I]], <i8 7, i8 7, i8 7, i8 7>
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq <4 x i8> [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr <4 x i16> [[ADD]], <i16 15, i16 15, i16 15, i16 15>
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc <4 x i16> [[SHR4_I]] to <4 x i8>
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor <4 x i8> [[CONV5_I]], <i8 127, i8 127, i8 127, i8 127>
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD]], <i16 -1, i16 -1, i16 -1, i16 -1>
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select <4 x i1> [[CMP_NOT_I]], <4 x i8> [[CONV1_I]], <4 x i8> [[XOR_I]]
>   ; CHECK-NEXT:    ret <4 x i8> [[COND_I]]
>   ;
> @@ -211,9 +207,8 @@ define <4 x i8> @testv4i16i8add(<4 x i8> %a, <4 x i8> %b) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc <4 x i16> [[ADD]] to <4 x i8>
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr <4 x i8> [[CONV1_I]], <i8 7, i8 7, i8 7, i8 7>
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq <4 x i8> [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr <4 x i16> [[ADD]], <i16 15, i16 15, i16 15, i16 15>
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc <4 x i16> [[SHR4_I]] to <4 x i8>
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor <4 x i8> [[CONV5_I]], <i8 127, i8 127, i8 127, i8 127>
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD]], <i16 -1, i16 -1, i16 -1, i16 -1>
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select <4 x i1> [[CMP_NOT_I]], <4 x i8> [[CONV1_I]], <4 x i8> [[XOR_I]]
>   ; CHECK-NEXT:    ret <4 x i8> [[COND_I]]
>   ;
> @@ -239,9 +234,8 @@ define i8 @testi16i8_revcmp(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -264,9 +258,8 @@ define i8 @testi16i8_revselect(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
>   ; CHECK-NEXT:    [[CMP_NOT_I_NOT:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I_NOT]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -332,9 +325,8 @@ define i8 @badimm1(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -357,9 +349,8 @@ define i8 @badimm2(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 6
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -407,9 +398,8 @@ define i8 @badimm4(i16 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i16 [[ADD]], 15
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i16 [[SHR4_I]] to i8
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i8 [[CONV5_I]], 126
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i8 126, i8 -127
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i8 [[CONV1_I]], i8 [[XOR_I]]
>   ; CHECK-NEXT:    ret i8 [[COND_I]]
>   ;
> @@ -434,9 +424,8 @@ define i32 @oneusexor(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    call void @use(i32 [[XOR_I]])
>   ; CHECK-NEXT:    ret i32 [[COND_I]]
> @@ -461,9 +450,8 @@ define i32 @oneuseconv(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    call void @use(i32 [[CONV1_I]])
>   ; CHECK-NEXT:    ret i32 [[COND_I]]
> @@ -488,9 +476,8 @@ define i32 @oneusecmp(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    call void @use1(i1 [[CMP_NOT_I]])
>   ; CHECK-NEXT:    ret i32 [[COND_I]]
> @@ -515,9 +502,8 @@ define i32 @oneuseboth(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    call void @use(i32 [[XOR_I]])
>   ; CHECK-NEXT:    call void @use(i32 [[CONV1_I]])
> @@ -544,9 +530,8 @@ define i32 @oneusethree(i64 %add) {
>   ; CHECK-NEXT:    [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
>   ; CHECK-NEXT:    [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
>   ; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
> -; CHECK-NEXT:    [[SHR4_I:%.*]] = ashr i64 [[ADD]], 63
> -; CHECK-NEXT:    [[CONV5_I:%.*]] = trunc i64 [[SHR4_I]] to i32
> -; CHECK-NEXT:    [[XOR_I:%.*]] = xor i32 [[CONV5_I]], 2147483647
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD]], -1
> +; CHECK-NEXT:    [[XOR_I:%.*]] = select i1 [[TMP1]], i32 2147483647, i32 -2147483648
>   ; CHECK-NEXT:    [[COND_I:%.*]] = select i1 [[CMP_NOT_I]], i32 [[CONV1_I]], i32 [[XOR_I]]
>   ; CHECK-NEXT:    call void @use(i32 [[XOR_I]])
>   ; CHECK-NEXT:    call void @use(i32 [[CONV1_I]])
>
> diff  --git a/llvm/test/Transforms/InstCombine/xor-ashr.ll b/llvm/test/Transforms/InstCombine/xor-ashr.ll
> index 146206b43f1e7..570a2b33fd59a 100644
> --- a/llvm/test/Transforms/InstCombine/xor-ashr.ll
> +++ b/llvm/test/Transforms/InstCombine/xor-ashr.ll
> @@ -7,8 +7,8 @@ declare void @use32(i32)
>   
>   define i8 @testi8i8(i8 %add) {
>   ; CHECK-LABEL: @testi8i8(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr i8 [[ADD:%.*]], 7
> -; CHECK-NEXT:    [[X:%.*]] = xor i8 [[SH]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8 [[ADD:%.*]], -1
> +; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
>   ; CHECK-NEXT:    ret i8 [[X]]
>   ;
>     %sh = ashr i8 %add, 7
> @@ -18,9 +18,8 @@ define i8 @testi8i8(i8 %add) {
>   
>   define i8 @testi16i8(i16 %add) {
>   ; CHECK-LABEL: @testi16i8(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr i16 [[ADD:%.*]], 15
> -; CHECK-NEXT:    [[T:%.*]] = trunc i16 [[SH]] to i8
> -; CHECK-NEXT:    [[X:%.*]] = xor i8 [[T]], 27
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD:%.*]], -1
> +; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i8 27, i8 -28
>   ; CHECK-NEXT:    ret i8 [[X]]
>   ;
>     %sh = ashr i16 %add, 15
> @@ -31,9 +30,8 @@ define i8 @testi16i8(i16 %add) {
>   
>   define i32 @testi64i32(i64 %add) {
>   ; CHECK-LABEL: @testi64i32(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr i64 [[ADD:%.*]], 63
> -; CHECK-NEXT:    [[T:%.*]] = trunc i64 [[SH]] to i32
> -; CHECK-NEXT:    [[X:%.*]] = xor i32 [[T]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD:%.*]], -1
> +; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i32 127, i32 -128
>   ; CHECK-NEXT:    ret i32 [[X]]
>   ;
>     %sh = ashr i64 %add, 63
> @@ -44,8 +42,8 @@ define i32 @testi64i32(i64 %add) {
>   
>   define i128 @testi128i128(i128 %add) {
>   ; CHECK-LABEL: @testi128i128(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr i128 [[ADD:%.*]], 127
> -; CHECK-NEXT:    [[X:%.*]] = xor i128 [[SH]], 27
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i128 [[ADD:%.*]], -1
> +; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i128 27, i128 -28
>   ; CHECK-NEXT:    ret i128 [[X]]
>   ;
>     %sh = ashr i128 %add, 127
> @@ -55,9 +53,8 @@ define i128 @testi128i128(i128 %add) {
>   
>   define <4 x i8> @testv4i16i8(<4 x i16> %add) {
>   ; CHECK-LABEL: @testv4i16i8(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr <4 x i16> [[ADD:%.*]], <i16 15, i16 15, i16 15, i16 15>
> -; CHECK-NEXT:    [[T:%.*]] = trunc <4 x i16> [[SH]] to <4 x i8>
> -; CHECK-NEXT:    [[X:%.*]] = xor <4 x i8> [[T]], <i8 27, i8 27, i8 27, i8 27>
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], <i16 -1, i16 -1, i16 -1, i16 -1>
> +; CHECK-NEXT:    [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 27, i8 27, i8 27, i8 27>, <4 x i8> <i8 -28, i8 -28, i8 -28, i8 -28>
>   ; CHECK-NEXT:    ret <4 x i8> [[X]]
>   ;
>     %sh = ashr <4 x i16> %add, <i16 15, i16 15, i16 15, i16 15>
> @@ -68,9 +65,8 @@ define <4 x i8> @testv4i16i8(<4 x i16> %add) {
>   
>   define <4 x i8> @testv4i16i8_undef(<4 x i16> %add) {
>   ; CHECK-LABEL: @testv4i16i8_undef(
> -; CHECK-NEXT:    [[SH:%.*]] = ashr <4 x i16> [[ADD:%.*]], <i16 15, i16 undef, i16 15, i16 15>
> -; CHECK-NEXT:    [[T:%.*]] = trunc <4 x i16> [[SH]] to <4 x i8>
> -; CHECK-NEXT:    [[X:%.*]] = xor <4 x i8> [[T]], <i8 27, i8 27, i8 undef, i8 27>
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], <i16 -1, i16 -1, i16 -1, i16 -1>
> +; CHECK-NEXT:    [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 27, i8 27, i8 undef, i8 27>, <4 x i8> <i8 -28, i8 -28, i8 undef, i8 -28>
>   ; CHECK-NEXT:    ret <4 x i8> [[X]]
>   ;
>     %sh = ashr <4 x i16> %add, <i16 15, i16 undef, i16 15, i16 15>
> @@ -112,9 +108,9 @@ define i16 @extrause(i16 %add) {
>   define i16 @extrause_trunc1(i32 %add) {
>   ; CHECK-LABEL: @extrause_trunc1(
>   ; CHECK-NEXT:    [[SH:%.*]] = ashr i32 [[ADD:%.*]], 31
> -; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[SH]] to i16
>   ; CHECK-NEXT:    call void @use32(i32 [[SH]])
> -; CHECK-NEXT:    [[X:%.*]] = xor i16 [[T]], 127
> +; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[ADD]], -1
> +; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i16 127, i16 -128
>   ; CHECK-NEXT:    ret i16 [[X]]
>   ;
>     %sh = ashr i32 %add, 31
>
>
>          
> _______________________________________________
> 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