diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index c60a290ce72e0..7092fb5e509bb 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1510,6 +1510,7 @@ InstCombinerImpl::foldICmpTruncWithTruncOrExt(ICmpInst &Cmp, std::swap(X, Y); Pred = Cmp.getSwappedPredicate(Pred); } + YIsSExt = !(NoWrapFlags & TruncInst::NoUnsignedWrap); } // Try to match icmp (trunc nuw X), (zext Y) else if (!Cmp.isSigned() && diff --git a/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll b/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll index 0a8bf013dc55d..a1757fbb84b23 100644 --- a/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll +++ b/llvm/test/Transforms/InstCombine/icmp-of-trunc-ext.ll @@ -568,3 +568,77 @@ define i1 @trunc_equality_both_sext(i32 %x, i8 %y) { %c = icmp ne i16 %xt, %ye ret i1 %c } + +define i1 @test_eq1(i32 %x, i16 %y) { +; CHECK-LABEL: @test_eq1( +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nsw i32 %x to i8 + %conv2 = trunc nsw i16 %y to i8 + %cond = icmp eq i8 %conv1, %conv2 + ret i1 %cond +} + +; FIXME: It is weird that we generate truncs for test_eq2, but not for test_eq1. + +define i1 @test_eq2(i32 %x, i16 %y) { +; CHECK-LABEL: @test_eq2( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; CHECK-NEXT: [[COND:%.*]] = icmp eq i16 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nsw i32 %x to i8 + %conv2 = trunc nsw i16 %y to i8 + %cond = icmp eq i8 %conv2, %conv1 + ret i1 %cond +} + +define i1 @test_ult(i32 %x, i16 %y) { +; CHECK-LABEL: @test_ult( +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32 +; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nsw i32 %x to i8 + %conv2 = trunc nsw i16 %y to i8 + %cond = icmp ult i8 %conv1, %conv2 + ret i1 %cond +} + +define i1 @test_slt(i32 %x, i16 %y) { +; CHECK-LABEL: @test_slt( +; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[Y:%.*]] to i32 +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nsw i32 %x to i8 + %conv2 = trunc nsw i16 %y to i8 + %cond = icmp slt i8 %conv1, %conv2 + ret i1 %cond +} + +define i1 @test_ult_nuw(i32 %x, i16 %y) { +; CHECK-LABEL: @test_ult_nuw( +; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[Y:%.*]] to i32 +; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nuw nsw i32 %x to i8 + %conv2 = trunc nuw nsw i16 %y to i8 + %cond = icmp ult i8 %conv1, %conv2 + ret i1 %cond +} + +define i1 @test_slt_nuw(i32 %x, i16 %y) { +; CHECK-LABEL: @test_slt_nuw( +; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[Y:%.*]] to i32 +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[TMP1]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv1 = trunc nuw nsw i32 %x to i8 + %conv2 = trunc nuw nsw i16 %y to i8 + %cond = icmp slt i8 %conv1, %conv2 + ret i1 %cond +}