diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index ccf918f0b6dbe..9ca8194b44f8f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -977,8 +977,7 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) { // trunc ( OP i8 C1, V1) to i1 -> icmp eq V1, log_2(C1) iff C1 is power of 2 if (DestWidth == 1 && match(Src, m_Shr(m_Power2(C1), m_Value(V1)))) { Value *Right = ConstantInt::get(V1->getType(), C1->countr_zero()); - Value *Icmp = Builder.CreateICmpEQ(V1, Right); - return replaceInstUsesWith(Trunc, Icmp); + return new ICmpInst(ICmpInst::ICMP_EQ, V1, Right); } // OP = { lshr, ashr } @@ -986,8 +985,15 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) { // power of 2 if (DestWidth == 1 && match(Src, m_Shr(m_LowBitMask(C1), m_Value(V1)))) { Value *Right = ConstantInt::get(V1->getType(), C1->countr_one()); - Value *Icmp = Builder.CreateICmpULT(V1, Right); - return replaceInstUsesWith(Trunc, Icmp); + return new ICmpInst(ICmpInst::ICMP_ULT, V1, Right); + } + + // OP = { lshr, ashr } + // trunc ( OP i8 C1, V1) to i1 -> icmp ugt V1, cttz(C1) - 1 iff (C1) is + // negative power of 2 + if (DestWidth == 1 && match(Src, m_Shr(m_NegatedPower2(C1), m_Value(V1)))) { + Value *Right = ConstantInt::get(V1->getType(), C1->countr_zero()); + return new ICmpInst(ICmpInst::ICMP_UGE, V1, Right); } return Changed ? &Trunc : nullptr; diff --git a/llvm/test/Transforms/InstCombine/trunc-lshr.ll b/llvm/test/Transforms/InstCombine/trunc-lshr.ll index c443b35cb1c1e..0e996e5d017fe 100644 --- a/llvm/test/Transforms/InstCombine/trunc-lshr.ll +++ b/llvm/test/Transforms/InstCombine/trunc-lshr.ll @@ -219,3 +219,77 @@ define i1 @negative_test_fold_ashr(i8 %x) { %trunc = trunc i8 %ashr to i1 ret i1 %trunc } + +define i1 @fold_lshr_negated_power_of_2(i8 %x) { +; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %lshr = lshr i8 -16, %x + %trunc = trunc i8 %lshr to i1 + ret i1 %trunc +} + +define i1 @fold_ashr_negated_power_of_2(i8 %x) { +; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %ashr = ashr i8 -16, %x + %trunc = trunc i8 %ashr to i1 + ret i1 %trunc +} + +define i1 @fold_lshr_negated_power_of_2_multi_use(i8 %x) { +; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2_multi_use( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -16, [[X]] +; CHECK-NEXT: call void @use(i8 [[LSHR]]) +; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %lshr = lshr i8 -16, %x + call void @use(i8 %lshr) + %trunc = trunc i8 %lshr to i1 + ret i1 %trunc +} + +define i1 @fold_ashr_negated_power_of_2_multi_use(i8 %x) { +; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2_multi_use( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[ASHR:%.*]] = ashr i8 -16, [[X]] +; CHECK-NEXT: call void @use(i8 [[ASHR]]) +; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %ashr = ashr i8 -16, %x + call void @use(i8 %ashr) + %trunc = trunc i8 %ashr to i1 + ret i1 %trunc +} + +define i1 @negative_test_fold_lshr_negated_power_of_2(i8 %x) { +; CHECK-LABEL: define i1 @negative_test_fold_lshr_negated_power_of_2( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -17, [[X]] +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[LSHR]] to i1 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %lshr = lshr i8 -17, %x + %trunc = trunc i8 %lshr to i1 + ret i1 %trunc +} + +define i1 @negative_test_fold_ashr_negated_power_of_2(i8 %x) { +; CHECK-LABEL: define i1 @negative_test_fold_ashr_negated_power_of_2( +; CHECK-SAME: i8 [[X:%.*]]) { +; CHECK-NEXT: [[ASHR1:%.*]] = lshr i8 -17, [[X]] +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[ASHR1]] to i1 +; CHECK-NEXT: ret i1 [[TRUNC]] +; + %ashr = ashr i8 -17, %x + %trunc = trunc i8 %ashr to i1 + ret i1 %trunc +}