[PATCH] D33172: [InstCombine] Simpify inverted predicates in 'or'

Brian Gesiak via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 14 10:50:41 PDT 2017


modocache created this revision.

Addresses PR#32791 (https://bugs.llvm.org//show_bug.cgi?id=32791).

When attempting to simplify an 'or' instruction, check whether its operands are
the results of 'select' instructions, and whether those instructions are the
inverse of one another (that is, their predicate are the inverse of one another,
but their true and false conditions are identical). If they are, the 'or' can
be simplified to a single 'select' instruction.


https://reviews.llvm.org/D33172

Files:
  lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  test/Transforms/InstCombine/logical-select.ll


Index: test/Transforms/InstCombine/logical-select.ll
===================================================================
--- test/Transforms/InstCombine/logical-select.ll
+++ test/Transforms/InstCombine/logical-select.ll
@@ -62,6 +62,22 @@
   ret i32 %t3
 }
 
+; PR32791 - https://bugs.llvm.org//show_bug.cgi?id=32791
+; Fold two selects with inverted predicates and zero operands.
+define i32 @pal(i32 %a, i32 %b, i32 %c, i32 %d) {
+; CHECK-LABEL: @pal(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 %a, %b
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], i32 %c, i32 %d
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %cmp1 = icmp slt i32 %a, %b
+  %sel1 = select i1 %cmp1, i32 %c, i32 0
+  %cmp2 = icmp sge i32 %a, %b
+  %sel2 = select i1 %cmp2, i32 %d, i32 0
+  %or = or i32 %sel1, %sel2
+  ret i32 %or
+}
+
 define i32 @par(i32 %a, i32 %b, i32 %c, i32 %d) {
 ; CHECK-LABEL: @par(
 ; CHECK-NEXT:    [[T0:%.*]] = icmp slt i32 %a, %b
Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2266,6 +2266,26 @@
     }
   }
 
+  // If the comparison is with the results of two select instructions, check
+  // whether those conditions are inverse icmp instructions. If so, simplify to
+  // a single select on one of the conditions.
+  {
+    auto Op0Select = dyn_cast<SelectInst>(Op0);
+    auto Op1Select = dyn_cast<SelectInst>(Op1);
+    if (Op0Select && Op1Select) {
+      auto Op0Cmp = dyn_cast<CmpInst>(Op0Select->getCondition());
+      auto Op1Cmp = dyn_cast<CmpInst>(Op1Select->getCondition());
+      if (Op0Cmp && Op1Cmp &&
+          Op0Cmp->getPredicate() == Op1Cmp->getInversePredicate() &&
+          Op0Cmp->getOperand(0) == Op1Cmp->getOperand(0) &&
+          Op0Cmp->getOperand(1) == Op1Cmp->getOperand(1)) {
+            return SelectInst::Create(Op0Select->getCondition(),
+                                      Op0Select->getTrueValue(),
+                                      Op1Select->getTrueValue());
+      }
+    }
+  }
+
   return Changed ? &I : nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33172.98927.patch
Type: text/x-patch
Size: 2165 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170514/02d52448/attachment.bin>


More information about the llvm-commits mailing list