From d307174e1d9e66a9e5a1e936ac3736343c3fe381 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 1 Apr 2020 09:34:33 +0100 Subject: [PATCH] [ConstantRange] Use APInt::or/APInt::and for single elements. Currently ConstantRange::binaryAnd/binaryOr results are too pessimistic for single element constant ranges. If both operands are single element ranges, we can use APInt's AND and OR implementations directly. Note that some other binary operations on constant ranges can cover the single element cases naturally, but for OR and AND this unfortunately is not the case. Reviewers: nikic, spatel, lebedev.ri Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D76446 --- llvm/lib/IR/ConstantRange.cpp | 8 ++++++ llvm/test/Transforms/Attributor/range.ll | 6 ++--- .../Transforms/CorrelatedValuePropagation/range.ll | 31 +++++++++++++++++++--- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index b8c5753..eabaaa2 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -1196,6 +1196,10 @@ ConstantRange::binaryAnd(const ConstantRange &Other) const { 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()); @@ -1207,6 +1211,10 @@ ConstantRange::binaryOr(const ConstantRange &Other) const { 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/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll index 1e93e976..ef8cd52 100644 --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -1276,13 +1276,11 @@ define i32 @ret1or2(i1 %c) { define i1 @callee_range_1(i1 %c1, i1 %c2, i1 %c3) { ; OLD_PM-LABEL: define {{[^@]+}}@callee_range_1 ; OLD_PM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) -; OLD_PM-NEXT: [[F:%.*]] = and i1 true, true -; OLD_PM-NEXT: ret i1 [[F]] +; OLD_PM-NEXT: ret i1 true ; ; NEW_PM-LABEL: define {{[^@]+}}@callee_range_1 ; NEW_PM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) -; NEW_PM-NEXT: [[F:%.*]] = and i1 true, true -; NEW_PM-NEXT: ret i1 [[F]] +; NEW_PM-NEXT: ret i1 true ; ; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@callee_range_1 ; CGSCC_OLD_PM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll index 6315e3b..634c375 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll @@ -457,7 +457,7 @@ define i1 @test14_slt(i32 %a) { ; 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 @@ define i1 @test14_sgt(i32 %a) { ; 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 @@ define i1 @test14_ugt(i32 %a) { ; 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,31 @@ else: 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( -- 2.7.4