diff --git a/include/llvm/Analysis/CmpInstAnalysis.h b/include/llvm/Analysis/CmpInstAnalysis.h index 1079d5abc7f..3cc69d9fea2 100644 --- a/include/llvm/Analysis/CmpInstAnalysis.h +++ b/include/llvm/Analysis/CmpInstAnalysis.h @@ -64,7 +64,8 @@ namespace llvm { /// returned predicate is either == or !=. Returns false if decomposition /// fails. bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred, - Value *&X, APInt &Mask); + Value *&X, APInt &Mask, + bool LookThroughTrunc = true); } // end namespace llvm diff --git a/lib/Analysis/CmpInstAnalysis.cpp b/lib/Analysis/CmpInstAnalysis.cpp index c879b8729dc..159c1a2d135 100644 --- a/lib/Analysis/CmpInstAnalysis.cpp +++ b/lib/Analysis/CmpInstAnalysis.cpp @@ -66,9 +66,11 @@ bool llvm::PredicatesFoldable(ICmpInst::Predicate p1, ICmpInst::Predicate p2) { bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred, - Value *&X, APInt &Mask) { + Value *&X, APInt &Mask, bool LookThruTrunc) { + using namespace PatternMatch; + const APInt *C; - if (!match(RHS, PatternMatch::m_APInt(C))) + if (!match(RHS, m_APInt(C))) return false; switch (Pred) { @@ -132,6 +134,11 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, break; } - X = LHS; + if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) { + Mask = Mask.zext(X->getType()->getScalarSizeInBits()); + } else { + X = LHS; + } + return true; } diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index d155f6b4803..94d71817049 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -3629,19 +3629,6 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS, if (!decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask)) return nullptr; - unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits(); - if (!BitWidth) - return nullptr; - - Value *ExtX; - if (match(X, m_Trunc(m_Value(ExtX))) && - (ExtX == TrueVal || ExtX == FalseVal)) { - // icmp slt (trunc X), 0 <--> icmp ne (and X, C), 0 - // icmp sgt (trunc X), -1 <--> icmp eq (and X, C), 0 - X = ExtX; - Mask = Mask.zext(BitWidth); - } - return simplifySelectBitTest(TrueVal, FalseVal, X, &Mask, Pred == ICmpInst::ICMP_EQ); } diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 11602ab101e..83aeda5935e 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -724,7 +724,7 @@ Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI, ICmpInst::Predicate Pred = ICI->getPredicate(); Value *X; APInt Mask; - if (decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask)) { + if (decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask, false)) { if (Mask.isSignMask()) { assert(X == CmpLHS && "Expected to use the compare input directly"); assert(ICmpInst::isEquality(Pred) && "Expected equality predicate"); diff --git a/test/Transforms/InstCombine/bit-checks.ll b/test/Transforms/InstCombine/bit-checks.ll index 3be67690431..1ecd305e807 100644 --- a/test/Transforms/InstCombine/bit-checks.ll +++ b/test/Transforms/InstCombine/bit-checks.ll @@ -520,12 +520,9 @@ define i32 @main7g(i32 %argc, i32 %argc2, i32 %argc3, i32 %argc4, i32 %argc5) { define i32 @main8(i32 %argc) { ; CHECK-LABEL: @main8( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARGC:%.*]], 64 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0 -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %and = and i32 %argc, 64 @@ -539,12 +536,9 @@ define i32 @main8(i32 %argc) { define i32 @main9(i32 %argc) { ; CHECK-LABEL: @main9( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARGC:%.*]], 64 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 192 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %and = and i32 %argc, 64 @@ -558,12 +552,9 @@ define i32 @main9(i32 %argc) { define i32 @main10(i32 %argc) { ; CHECK-LABEL: @main10( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARGC:%.*]], 64 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %and = and i32 %argc, 64 @@ -577,12 +568,9 @@ define i32 @main10(i32 %argc) { define i32 @main11(i32 %argc) { ; CHECK-LABEL: @main11( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARGC:%.*]], 64 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 192 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %and = and i32 %argc, 64 @@ -596,12 +584,9 @@ define i32 @main11(i32 %argc) { define i32 @main12(i32 %argc) { ; CHECK-LABEL: @main12( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i16 [[TRUNC]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0 -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %trunc = trunc i32 %argc to i16 @@ -615,12 +600,9 @@ define i32 @main12(i32 %argc) { define i32 @main13(i32 %argc) { ; CHECK-LABEL: @main13( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp slt i16 [[TRUNC]], 0 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 32896 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %trunc = trunc i32 %argc to i16 @@ -634,12 +616,9 @@ define i32 @main13(i32 %argc) { define i32 @main14(i32 %argc) { ; CHECK-LABEL: @main14( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp sgt i16 [[TRUNC]], -1 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %trunc = trunc i32 %argc to i16 @@ -653,12 +632,9 @@ define i32 @main14(i32 %argc) { define i32 @main15(i32 %argc) { ; CHECK-LABEL: @main15( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp sgt i16 [[TRUNC]], -1 -; CHECK-NEXT: [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8 -; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1 -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]] -; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 32896 +; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2 ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; %trunc = trunc i32 %argc to i16