Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1966,6 +1966,15 @@ return new ICmpInst(Pred, Builder->CreateTrunc(X, TruncTy), NewC); } + // when the shift is nuw and pred is >u or <=, then comparison only really + // happens in the pre-shifted bits. + if (Shl->hasNoUnsignedWrap() && + (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE)) { + Type *CTy = IntegerType::get(Cmp.getContext(), C->getBitWidth()); + Value *NewC = ConstantInt::get(CTy, C->lshr(*ShiftAmt)); + return new ICmpInst(Pred, X, NewC); + } + return nullptr; } Index: test/Transforms/InstCombine/icmp-shl-zext-simplify.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/icmp-shl-zext-simplify.ll @@ -0,0 +1,73 @@ +; RUN: opt %s -instcombine -S | FileCheck %s + +define i32 @icmp_ugt_16(i16) { +; CHECK-LABEL: @icmp_ugt_16 +; CHECK-NEXT: icmp ne i16 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i16 %0 to i64 + %c = shl i64 %b, 16 + %d = icmp ugt i64 %c, 65535 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @icmp_ule_16(i16) { +; CHECK-LABEL: @icmp_ule_16 +; CHECK-NEXT: icmp eq i16 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i16 %0 to i64 + %c = shl i64 %b, 16 + %d = icmp ule i64 %c, 65535 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @icmp_ugt_32(i32) { +; CHECK-LABEL: @icmp_ugt_32 +; CHECK-NEXT: icmp ne i32 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i32 %0 to i64 + %c = shl i64 %b, 32 + %d = icmp ugt i64 %c, 4294967295 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @icmp_ule_32(i32) { +; CHECK-LABEL: @icmp_ule_32 +; CHECK-NEXT: icmp eq i32 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i32 %0 to i64 + %c = shl i64 %b, 32 + %d = icmp ule i64 %c, 4294967295 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @icmp_ugt_64(i64) { +; CHECK-LABEL: @icmp_ugt_64 +; CHECK-NEXT: icmp ne i64 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i64 %0 to i128 + %c = shl i128 %b, 64 + %d = icmp ugt i128 %c, 18446744073709551615 + %rv = zext i1 %d to i32 + ret i32 %rv +} + +define i32 @icmp_ule_64(i64) { +; CHECK-LABEL: @icmp_ule_64 +; CHECK-NEXT: icmp eq i64 %0, 0 +; CHECK-NEXT: zext +; CHECK-NEXT: ret + %b = zext i64 %0 to i128 + %c = shl i128 %b, 64 + %d = icmp ule i128 %c, 18446744073709551615 + %rv = zext i1 %d to i32 + ret i32 %rv +}