diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1194,6 +1194,10 @@ if (isEmptySet() || Other.isEmptySet()) return getEmpty(); + // Use APInt's implementation of AND for single element ranges. + if (isSingleElement() && Other.isSingleElement()) + return {*getSingleElement() & *Other.getSingleElement()}; + // TODO: replace this with something less conservative APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); @@ -1205,6 +1209,10 @@ if (isEmptySet() || Other.isEmptySet()) return getEmpty(); + // Use APInt's implementation of OR for single element ranges. + if (isSingleElement() && Other.isSingleElement()) + return {*getSingleElement() | *Other.getSingleElement()}; + // TODO: replace this with something less conservative APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll @@ -457,7 +457,7 @@ ; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false -; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK-NEXT: ret i1 false ; CHECK: else: ; CHECK-NEXT: ret i1 false ; @@ -508,7 +508,7 @@ ; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false -; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK-NEXT: ret i1 false ; CHECK: else: ; CHECK-NEXT: ret i1 false ; @@ -585,7 +585,7 @@ ; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] ; CHECK: then: ; CHECK-NEXT: [[RESULT:%.*]] = or i1 false, false -; CHECK-NEXT: ret i1 [[RESULT]] +; CHECK-NEXT: ret i1 false ; CHECK: else: ; CHECK-NEXT: ret i1 false ; @@ -629,6 +629,32 @@ ret i1 false } +define i1 @test14_ugt_and(i32 %a) { +; CHECK-LABEL: @test14_ugt_and( +; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A_OFF]], 8 +; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]] +; CHECK: then: +; CHECK-NEXT: [[RESULT:%.*]] = and i1 false, false +; CHECK-NEXT: ret i1 false +; CHECK: else: +; CHECK-NEXT: ret i1 false +; + %a.off = add i32 %a, -8 + %cmp = icmp ugt i32 %a.off, 8 + br i1 %cmp, label %then, label %else + +then: + %dead.1 = icmp eq i32 %a, 8 + %dead.2 = icmp eq i32 %a, 16 + %result = and i1 %dead.1, %dead.2 + ret i1 %result + +else: + ret i1 false +} + + @limit = external global i32 define i1 @test15(i32 %a) { ; CHECK-LABEL: @test15(