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

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 3 19:26:05 PDT 2021


Hi David,

This change seems to be causing an infinite loop in the compiler when compiling one of our internal tests. I have put a reduced test case in PR52397, can you take a look?

Douglas Yung

-----Original Message-----
From: llvm-commits <llvm-commits-bounces at lists.llvm.org> On Behalf Of David Green via llvm-commits
Sent: Friday, October 29, 2021 3:19
To: llvm-commits at lists.llvm.org
Subject: [llvm] 9020e22 - [InstCombine] Convert xor (ashr X, BW-1), C -> select(X >=s 0, C, ~C)


Author: David Green
Date: 2021-10-29T11:19:20+01:00
New Revision: 9020e22a876e15afd7b5d13ac3abf180b5cf9343

URL: https://urldefense.com/v3/__https://github.com/llvm/llvm-project/commit/9020e22a876e15afd7b5d13ac3abf180b5cf9343__;!!JmoZiZGBv3RvKRSx!uHbHAMChD-jKyz3pJ75JWHVyrHVs7idqb5ZTWs_ea9aOYhkCXn0HZczaM3pX5X7N0w$
DIFF: https://urldefense.com/v3/__https://github.com/llvm/llvm-project/commit/9020e22a876e15afd7b5d13ac3abf180b5cf9343.diff__;!!JmoZiZGBv3RvKRSx!uHbHAMChD-jKyz3pJ75JWHVyrHVs7idqb5ZTWs_ea9aOYhkCXn0HZczaM3qc-cWgLw$ 

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://urldefense.com/v3/__https://alive2.llvm.org/ce/z/NJ85qY__;!!JmoZiZGBv3RvKRSx!uHbHAMChD-jKyz3pJ75JWHVyrHVs7idqb5ZTWs_ea9aOYhkCXn0HZczaM3qVyWLg2Q$ 

This is a fairly general version of a fold that helps pull saturating arithmetic into a canonical form.

Differential Revision: https://urldefense.com/v3/__https://reviews.llvm.org/D109151__;!!JmoZiZGBv3RvKRSx!uHbHAMChD-jKyz3pJ75JWHVyrHVs7idqb5ZTWs_ea9aOYhkCXn0HZczaM3r4UGaNnw$ 

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://urldefense.com/v3/__https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits__;!!JmoZiZGBv3RvKRSx!uHbHAMChD-jKyz3pJ75JWHVyrHVs7idqb5ZTWs_ea9aOYhkCXn0HZczaM3reXBc8tQ$ 


More information about the llvm-commits mailing list