[llvm] 3039691 - [InstCombine] add `getFreeInverted` to perform folds for free inversion of op
Noah Goldstein via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 15:59:52 PST 2023
Author: Noah Goldstein
Date: 2023-11-20T17:59:27-06:00
New Revision: 3039691f53487289bab40a4f889810ffd91980c2
URL: https://github.com/llvm/llvm-project/commit/3039691f53487289bab40a4f889810ffd91980c2
DIFF: https://github.com/llvm/llvm-project/commit/3039691f53487289bab40a4f889810ffd91980c2.diff
LOG: [InstCombine] add `getFreeInverted` to perform folds for free inversion of op
With the current logic of `if(isFreeToInvert(Op)) return Not(Op)` its
fairly easy to either 1) cause regressions or 2) infinite loops
if the folds we have for `Not(Op)` ever de-sync with the cases we
know are freely invertible.
This patch adds `getFreeInverted` which is able to build the free
inverted op along with check for free inversion to alleviate this
problem.
Added:
Modified:
llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
llvm/test/Transforms/InstCombine/free-inversion.ll
llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
index 3fc16d0e803a6db..23086e42f98681f 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
@@ -233,66 +233,40 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
PatternMatch::m_Value()));
}
+ /// Return nonnull value if V is free to invert under the condition of
+ /// WillInvertAllUses.
+ /// If Builder is nonnull, it will return a simplified ~V.
+ /// If Builder is null, it will return an arbitrary nonnull value (not
+ /// dereferenceable).
+ /// If the inversion will consume instructions, `DoesConsume` will be set to
+ /// true. Otherwise it will be false.
+ static Value *getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
+ BuilderTy *Builder, bool &DoesConsume,
+ unsigned Depth);
+
+ static Value *getFreelyInverted(Value *V, bool WillInvertAllUses,
+ BuilderTy *Builder, bool &DoesConsume) {
+ DoesConsume = false;
+ return getFreelyInvertedImpl(V, WillInvertAllUses, Builder, DoesConsume,
+ /*Depth*/ 0);
+ }
+
+ static Value *getFreelyInverted(Value *V, bool WillInvertAllUses,
+ BuilderTy *Builder) {
+ bool Unused;
+ return getFreelyInverted(V, WillInvertAllUses, Builder, Unused);
+ }
+
/// Return true if the specified value is free to invert (apply ~ to).
/// This happens in cases where the ~ can be eliminated. If WillInvertAllUses
/// is true, work under the assumption that the caller intends to remove all
/// uses of V and only keep uses of ~V.
///
/// See also: canFreelyInvertAllUsersOf()
- static bool isFreeToInvertImpl(Value *V, bool WillInvertAllUses,
- bool &DoesConsume, unsigned Depth) {
- using namespace llvm::PatternMatch;
- // ~(~(X)) -> X.
- if (match(V, m_Not(m_Value()))) {
- DoesConsume = true;
- return true;
- }
-
- // Constants can be considered to be not'ed values.
- if (match(V, m_AnyIntegralConstant()))
- return true;
-
- if (Depth++ >= MaxAnalysisRecursionDepth)
- return false;
-
- // The rest of the cases require that we invert all uses so don't bother
- // doing the analysis if we know we can't use the result.
- if (!WillInvertAllUses)
- return false;
-
- // Compares can be inverted if all of their uses are being modified to use
- // the ~V.
- if (isa<CmpInst>(V))
- return true;
-
- Value *A, *B;
- // If `V` is of the form `A + B` then `-1 - V` can be folded into
- // `~B - A` or `~A - B` if we are willing to invert all of the uses.
- if (match(V, m_Add(m_Value(A), m_Value(B))))
- return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth) ||
- isFreeToInvertImpl(B, B->hasOneUse(), DoesConsume, Depth);
-
- // If `V` is of the form `A - B` then `-1 - V` can be folded into
- // `~A + B` if we are willing to invert all of the uses.
- if (match(V, m_Sub(m_Value(A), m_Value())))
- return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth);
-
- // LogicOps are special in that we canonicalize them at the cost of an
- // instruction.
- bool IsSelect = match(V, m_Select(m_Value(), m_Value(A), m_Value(B))) &&
- !shouldAvoidAbsorbingNotIntoSelect(*cast<SelectInst>(V));
- // Selects/min/max with invertible operands are freely invertible
- if (IsSelect || match(V, m_MaxOrMin(m_Value(A), m_Value(B))))
- return isFreeToInvertImpl(A, A->hasOneUse(), DoesConsume, Depth) &&
- isFreeToInvertImpl(B, B->hasOneUse(), DoesConsume, Depth);
-
- return false;
- }
-
static bool isFreeToInvert(Value *V, bool WillInvertAllUses,
bool &DoesConsume) {
- DoesConsume = false;
- return isFreeToInvertImpl(V, WillInvertAllUses, DoesConsume, /*Depth*/ 0);
+ return getFreelyInverted(V, WillInvertAllUses, /*Builder*/ nullptr,
+ DoesConsume) != nullptr;
}
static bool isFreeToInvert(Value *V, bool WillInvertAllUses) {
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 1910ebca4004ccc..cc2fb7dfe1565f3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4433,6 +4433,11 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {
if (Instruction *NewXor = foldNotXor(I, Builder))
return NewXor;
+ // TODO: Could handle multi-use better by checking if all uses of NotOp (other
+ // than I) can be inverted.
+ if (Value *R = getFreelyInverted(NotOp, NotOp->hasOneUse(), &Builder))
+ return replaceInstUsesWith(I, R);
+
return nullptr;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c6abcb4d547cd2d..e6088541349784b 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2106,6 +2106,110 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
return nullptr;
}
+Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
+ BuilderTy *Builder,
+ bool &DoesConsume, unsigned Depth) {
+ static Value *const NonNull = reinterpret_cast<Value *>(uintptr_t(1));
+ // ~(~(X)) -> X.
+ Value *A, *B;
+ if (match(V, m_Not(m_Value(A)))) {
+ DoesConsume = true;
+ return A;
+ }
+
+ Constant *C;
+ // Constants can be considered to be not'ed values.
+ if (match(V, m_ImmConstant(C)))
+ return ConstantExpr::getNot(C);
+
+ if (Depth++ >= MaxAnalysisRecursionDepth)
+ return nullptr;
+
+ // The rest of the cases require that we invert all uses so don't bother
+ // doing the analysis if we know we can't use the result.
+ if (!WillInvertAllUses)
+ return nullptr;
+
+ // Compares can be inverted if all of their uses are being modified to use
+ // the ~V.
+ if (auto *I = dyn_cast<CmpInst>(V)) {
+ if (Builder != nullptr)
+ return Builder->CreateCmp(I->getInversePredicate(), I->getOperand(0),
+ I->getOperand(1));
+ return NonNull;
+ }
+
+ // If `V` is of the form `A + B` then `-1 - V` can be folded into
+ // `(-1 - B) - A` if we are willing to invert all of the uses.
+ if (match(V, m_Add(m_Value(A), m_Value(B)))) {
+ if (auto *BV = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateSub(BV, A) : NonNull;
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateSub(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `A ^ ~B` then `~(A ^ ~B)` can be folded
+ // into `A ^ B` if we are willing to invert all of the uses.
+ if (match(V, m_Xor(m_Value(A), m_Value(B)))) {
+ if (auto *BV = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateXor(A, BV) : NonNull;
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateXor(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `B - A` then `-1 - V` can be folded into
+ // `A + (-1 - B)` if we are willing to invert all of the uses.
+ if (match(V, m_Sub(m_Value(A), m_Value(B)))) {
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateAdd(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ // If `V` is of the form `(~A) s>> B` then `~((~A) s>> B)` can be folded
+ // into `A s>> B` if we are willing to invert all of the uses.
+ if (match(V, m_AShr(m_Value(A), m_Value(B)))) {
+ if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth))
+ return Builder ? Builder->CreateAShr(AV, B) : NonNull;
+ return nullptr;
+ }
+
+ Value *Cond;
+ // LogicOps are special in that we canonicalize them at the cost of an
+ // instruction.
+ bool IsSelect = match(V, m_Select(m_Value(Cond), m_Value(A), m_Value(B))) &&
+ !shouldAvoidAbsorbingNotIntoSelect(*cast<SelectInst>(V));
+ // Selects/min/max with invertible operands are freely invertible
+ if (IsSelect || match(V, m_MaxOrMin(m_Value(A), m_Value(B)))) {
+ if (!getFreelyInvertedImpl(B, B->hasOneUse(), /*Builder*/ nullptr,
+ DoesConsume, Depth))
+ return nullptr;
+ if (Value *NotA = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
+ DoesConsume, Depth)) {
+ if (Builder != nullptr) {
+ Value *NotB = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
+ DoesConsume, Depth);
+ assert(NotB != nullptr &&
+ "Unable to build inverted value for known freely invertable op");
+ if (auto *II = dyn_cast<IntrinsicInst>(V))
+ return Builder->CreateBinaryIntrinsic(
+ getInverseMinMaxIntrinsic(II->getIntrinsicID()), NotA, NotB);
+ return Builder->CreateSelect(Cond, NotA, NotB);
+ }
+ return NonNull;
+ }
+ }
+
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Value *PtrOp = GEP.getOperand(0);
SmallVector<Value *, 8> Indices(GEP.indices());
diff --git a/llvm/test/Transforms/InstCombine/free-inversion.ll b/llvm/test/Transforms/InstCombine/free-inversion.ll
index 495028ccb970f21..d3b6a5801b53b6a 100644
--- a/llvm/test/Transforms/InstCombine/free-inversion.ll
+++ b/llvm/test/Transforms/InstCombine/free-inversion.ll
@@ -10,11 +10,9 @@ declare void @use.i8(i8)
define i8 @xor_1(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @xor_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[BA:%.*]] = xor i8 [[B]], [[A:%.*]]
-; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[B_NOT:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[B_NOT]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -27,11 +25,9 @@ define i8 @xor_1(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @xor_2(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @xor_2(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[AB:%.*]] = xor i8 [[B]], [[A:%.*]]
-; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[B_NOT:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[B_NOT]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_AB]]
;
%nx = xor i8 %x, -1
@@ -59,11 +55,9 @@ define i8 @xor_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @add_1(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @add_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[BA:%.*]] = add i8 [[B]], [[A:%.*]]
-; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = sub i8 [[TMP2]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -76,11 +70,9 @@ define i8 @add_1(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @add_2(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @add_2(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[AB:%.*]] = add i8 [[B]], [[A:%.*]]
-; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_AB:%.*]] = sub i8 [[TMP2]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_AB]]
;
%nx = xor i8 %x, -1
@@ -110,11 +102,9 @@ define i8 @add_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @sub_1(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @sub_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[B]], -1
-; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -145,11 +135,10 @@ define i8 @sub_2(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @sub_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @sub_fail(
; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
; CHECK-NEXT: call void @use.i8(i8 [[NX]])
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[B]], -1
-; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -163,11 +152,9 @@ define i8 @sub_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @ashr_1(i8 %a, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @ashr_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[BA:%.*]] = ashr i8 [[B]], [[A:%.*]]
-; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = ashr i8 [[TMP2]], [[A:%.*]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -197,13 +184,11 @@ define i8 @ashr_2_fail(i8 %a, i1 %c, i8 %x, i8 %y) {
define i8 @select_1(i1 %cc, i8 %na, i8 %aa, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @select_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[NA:%.*]], [[AA:%.*]]
-; CHECK-NEXT: [[A:%.*]] = xor i8 [[TMP1]], 45
-; CHECK-NEXT: [[AB:%.*]] = select i1 [[CC:%.*]], i8 [[A]], i8 [[B]]
-; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -46
+; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP3]]
+; CHECK-NEXT: [[NOT_AB:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP4]]
; CHECK-NEXT: ret i8 [[NOT_AB]]
;
%nx = xor i8 %x, -1
@@ -218,12 +203,10 @@ define i8 @select_1(i1 %cc, i8 %na, i8 %aa, i1 %c, i8 %x, i8 %y) {
define i8 @select_2(i1 %cc, i8 %na, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @select_2(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[A:%.*]] = xor i8 [[NA:%.*]], 45
-; CHECK-NEXT: [[BA:%.*]] = select i1 [[CC:%.*]], i8 [[B]], i8 [[A]]
-; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[NA:%.*]], -46
+; CHECK-NEXT: [[NOT_BA:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP3]]
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
@@ -271,13 +254,10 @@ define i1 @select_logic_and_fail(i1 %cc, i1 %c, i1 %x, i8 %y) {
define i8 @smin_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @smin_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[NNA:%.*]] = xor i8 [[NA:%.*]], -1
-; CHECK-NEXT: [[A:%.*]] = add i8 [[NNA]], [[AA:%.*]]
-; CHECK-NEXT: [[AB:%.*]] = call i8 @llvm.smin.i8(i8 [[A]], i8 [[B]])
-; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[NA:%.*]], [[AA:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]]
+; CHECK-NEXT: [[NOT_AB:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP3]])
; CHECK-NEXT: ret i8 [[NOT_AB]]
;
%nx = xor i8 %x, -1
@@ -324,13 +304,10 @@ define i8 @umin_1_fail(i1 %c, i8 %x, i8 %y) {
define i8 @smax_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @smax_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[NNA:%.*]] = xor i8 [[NA:%.*]], -1
-; CHECK-NEXT: [[A:%.*]] = sub i8 [[NNA]], [[AA:%.*]]
-; CHECK-NEXT: [[AB:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]])
-; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[NA:%.*]], [[AA:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]]
+; CHECK-NEXT: [[NOT_AB:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP1]], i8 [[TMP3]])
; CHECK-NEXT: ret i8 [[NOT_AB]]
;
%nx = xor i8 %x, -1
@@ -368,11 +345,9 @@ define i8 @smax_1_fail(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) {
define i8 @umax_1(i8 %na, i1 %c, i8 %x, i8 %y) {
; CHECK-LABEL: @umax_1(
-; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123
-; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]]
-; CHECK-NEXT: [[BA:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 85)
-; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: [[NOT_BA:%.*]] = call i8 @llvm.umin.i8(i8 [[TMP2]], i8 -86)
; CHECK-NEXT: ret i8 [[NOT_BA]]
;
%nx = xor i8 %x, -1
diff --git a/llvm/test/Transforms/InstCombine/icmp-of-or-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
index 839aa98a8b24e2f..4b8df439b846fb6 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
@@ -121,9 +121,9 @@ define i1 @or_ne_notY_eq_1s(i8 %x, i8 %y) {
define i1 @or_ne_notY_eq_1s_fail_bad_not(i8 %x, i8 %y) {
; CHECK-LABEL: @or_ne_notY_eq_1s_fail_bad_not(
-; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -2
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[NY]], [[X:%.*]]
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[OR]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = or i8 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP2]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%ny = xor i8 %y, -2
More information about the llvm-commits
mailing list