[llvm] r270019 - [GuardWidening] Use getEquivalentICmp to fold constant compares

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Wed May 18 20:53:19 PDT 2016


Author: sanjoy
Date: Wed May 18 22:53:17 2016
New Revision: 270019

URL: http://llvm.org/viewvc/llvm-project?rev=270019&view=rev
Log:
[GuardWidening] Use getEquivalentICmp to fold constant compares

`ConstantRange::getEquivalentICmp` is more general, and better
factored.

Modified:
    llvm/trunk/lib/Transforms/Scalar/GuardWidening.cpp
    llvm/trunk/test/Transforms/GuardWidening/basic.ll

Modified: llvm/trunk/lib/Transforms/Scalar/GuardWidening.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GuardWidening.cpp?rev=270019&r1=270018&r2=270019&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GuardWidening.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GuardWidening.cpp Wed May 18 22:53:17 2016
@@ -356,21 +356,31 @@ bool GuardWideningImpl::widenCondCommon(
     if (match(Cond0, m_ICmp(Pred0, m_Value(LHS), m_ConstantInt(RHS0))) &&
         match(Cond1, m_ICmp(Pred1, m_Specific(LHS), m_ConstantInt(RHS1)))) {
 
-      // TODO: This logic should be generalized and refactored into a new
-      // Constant::getEquivalentICmp helper.
-      if (Pred0 == ICmpInst::ICMP_NE && RHS0->isZero())
-        Pred0 = ICmpInst::ICMP_UGT;
-      if (Pred1 == ICmpInst::ICMP_NE && RHS1->isZero())
-        Pred1 = ICmpInst::ICMP_UGT;
+      ConstantRange CR0 =
+          ConstantRange::makeExactICmpRegion(Pred0, RHS0->getValue());
+      ConstantRange CR1 =
+          ConstantRange::makeExactICmpRegion(Pred1, RHS1->getValue());
 
-      if (Pred0 == ICmpInst::ICMP_UGT && Pred1 == ICmpInst::ICMP_UGT) {
+      // SubsetIntersect is a subset of the actual mathematical intersection of
+      // CR0 and CR1, while SupersetIntersect is a superset of the the actual
+      // mathematical intersection.  If these two ConstantRanges are equal, then
+      // we know we were able to represent the actual mathematical intersection
+      // of CR0 and CR1, and can use the same to generate an icmp instruction.
+      //
+      // Given what we're doing here and the semantics of guards, it would
+      // actually be correct to just use SubsetIntersect, but that may be too
+      // aggressive in cases we care about.
+      auto SubsetIntersect = CR0.inverse().unionWith(CR1.inverse()).inverse();
+      auto SupersetIntersect = CR0.intersectWith(CR1);
+
+      APInt NewRHSAP;
+      CmpInst::Predicate Pred;
+      if (SubsetIntersect == SupersetIntersect &&
+          SubsetIntersect.getEquivalentICmp(Pred, NewRHSAP)) {
         if (InsertPt) {
-          ConstantInt *NewRHS =
-              RHS0->getValue().ugt(RHS1->getValue()) ? RHS0 : RHS1;
-          Result = new ICmpInst(InsertPt, ICmpInst::ICMP_UGT, LHS, NewRHS,
-                                "wide.chk");
+          ConstantInt *NewRHS = ConstantInt::get(Cond0->getContext(), NewRHSAP);
+          Result = new ICmpInst(InsertPt, Pred, LHS, NewRHS, "wide.chk");
         }
-
         return true;
       }
     }

Modified: llvm/trunk/test/Transforms/GuardWidening/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/basic.ll?rev=270019&r1=270018&r2=270019&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/basic.ll (original)
+++ llvm/trunk/test/Transforms/GuardWidening/basic.ll Wed May 18 22:53:17 2016
@@ -126,7 +126,7 @@ leave:
 define void @f_5(i32 %a) {
 ; CHECK-LABEL: @f_5(
 entry:
-; CHECK:  %wide.chk = icmp ugt i32 %a, 10
+; CHECK:  %wide.chk = icmp uge i32 %a, 11
 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
 ; CHECK:  br i1 undef, label %left, label %right
 
@@ -335,3 +335,47 @@ entry:
   call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
   ret void
 }
+
+define void @f_13(i32 %a) {
+; CHECK-LABEL: @f_13(
+entry:
+; CHECK:  %wide.chk = icmp ult i32 %a, 10
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 14
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+  %cond_1 = icmp slt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}
+
+define void @f_14(i32 %a) {
+; CHECK-LABEL: @f_14(
+entry:
+; CHECK:  %cond_0 = icmp ult i32 %a, 14
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+; CHECK:  br i1 undef, label %left, label %right
+
+  %cond_0 = icmp ult i32 %a, 14
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
+  br i1 undef, label %left, label %right
+
+left:
+; CHECK: left:
+; CHECK:  %cond_1 = icmp sgt i32 %a, 10
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+
+  %cond_1 = icmp sgt i32 %a, 10
+  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
+  ret void
+
+right:
+  ret void
+}




More information about the llvm-commits mailing list