[llvm] r309817 - [InlineCost] Simplify more 'and' and 'or' operations.

Chad Rosier via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 2 07:40:42 PDT 2017


Author: mcrosier
Date: Wed Aug  2 07:40:42 2017
New Revision: 309817

URL: http://llvm.org/viewvc/llvm-project?rev=309817&view=rev
Log:
[InlineCost] Simplify more 'and' and 'or' operations.

Differential Revision: https://reviews.llvm.org/D35856

Added:
    llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll
Modified:
    llvm/trunk/lib/Analysis/InlineCost.cpp

Modified: llvm/trunk/lib/Analysis/InlineCost.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InlineCost.cpp?rev=309817&r1=309816&r2=309817&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Wed Aug  2 07:40:42 2017
@@ -207,6 +207,8 @@ class CallAnalyzer : public InstVisitor<
   bool visitCastInst(CastInst &I);
   bool visitUnaryInstruction(UnaryInstruction &I);
   bool visitCmpInst(CmpInst &I);
+  bool visitAnd(BinaryOperator &I);
+  bool visitOr(BinaryOperator &I);
   bool visitSub(BinaryOperator &I);
   bool visitBinaryOperator(BinaryOperator &I);
   bool visitLoad(LoadInst &I);
@@ -843,6 +845,34 @@ bool CallAnalyzer::visitCmpInst(CmpInst
   return false;
 }
 
+bool CallAnalyzer::visitOr(BinaryOperator &I) {
+  // This is necessary because the generic simplify instruction only works if
+  // both operands are constants.
+  for (unsigned i = 0; i < 2; ++i) {
+    if (ConstantInt *C = dyn_cast_or_null<ConstantInt>(
+            SimplifiedValues.lookup(I.getOperand(i))))
+      if (C->isAllOnesValue()) {
+        SimplifiedValues[&I] = C;
+        return true;
+      }
+  }
+  return Base::visitOr(I);
+}
+
+bool CallAnalyzer::visitAnd(BinaryOperator &I) {
+  // This is necessary because the generic simplify instruction only works if
+  // both operands are constants.
+  for (unsigned i = 0; i < 2; ++i) {
+    if (ConstantInt *C = dyn_cast_or_null<ConstantInt>(
+            SimplifiedValues.lookup(I.getOperand(i))))
+      if (C->isZero()) {
+        SimplifiedValues[&I] = C;
+        return true;
+      }
+  }
+  return Base::visitAnd(I);
+}
+
 bool CallAnalyzer::visitSub(BinaryOperator &I) {
   // Try to handle a special case: we can fold computing the difference of two
   // constant-related pointers.

Added: llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll?rev=309817&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll (added)
+++ llvm/trunk/test/Transforms/Inline/AArch64/logical-and-or.ll Wed Aug  2 07:40:42 2017
@@ -0,0 +1,94 @@
+; REQUIRES: asserts
+; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-gnu"
+
+; FIXME: Once the 'or' or 'and' is simplified the second compare is dead, but
+; the inline cost model has already added the cost.
+
+define i1 @outer1(i32 %a) {
+  %C = call i1 @inner1(i32 0, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner1
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i1 @inner1(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0         ; Simplifies to true
+  %tobool1 = icmp eq i32 %b, 0        ; Should be dead once 'or' is simplified
+  %or.cond = or i1 %tobool, %tobool1  ; Simplifies to true
+  ret i1 %or.cond                     ; Simplifies to ret i1 true
+}
+
+define i1 @outer2(i32 %a) {
+  %C = call i1 @inner2(i32 1, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner2
+; CHECK: NumInstructionsSimplified: 3
+; CHECK: NumInstructions: 4
+define i1 @inner2(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0          ; Simplifies to false
+  %tobool1 = icmp eq i32 %b, 0         ; Should be dead once 'and' is simplified
+  %and.cond = and i1 %tobool, %tobool1 ; Simplifies to false
+  ret i1 %and.cond                     ; Simplifies to ret i1 false
+}
+
+
+define i32 @outer3(i32 %a) {
+  %C = call i32 @inner3(i32 4294967295, i32 %a)
+  ret i32 %C
+}
+
+; CHECK: Analyzing call of inner3
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define i32 @inner3(i32 %a, i32 %b) {
+  %or.cond = or i32 %a, %b         ; Simplifies to 4294967295
+  ret i32 %or.cond                 ; Simplifies to ret i32 4294967295
+}
+
+
+define i32 @outer4(i32 %a) {
+  %C = call i32 @inner4(i32 0, i32 %a)
+  ret i32 %C
+}
+
+; CHECK: Analyzing call of inner4
+; CHECK: NumInstructionsSimplified: 2
+; CHECK: NumInstructions: 2
+define i32 @inner4(i32 %a, i32 %b) {
+  %and.cond = and i32 %a, %b       ; Simplifies to 0
+  ret i32 %and.cond                ; Simplifies to ret i32 0
+}
+
+define i1 @outer5(i32 %a) {
+  %C = call i1 @inner5(i32 0, i32 %a)
+  ret i1 %C
+}
+
+; CHECK: Analyzing call of inner5
+; CHECK: NumInstructionsSimplified: 4
+; CHECK: NumInstructions: 5
+define i1 @inner5(i32 %a, i32 %b) {
+  %tobool = icmp eq i32 %a, 0         ; Simplifies to true
+  %tobool1 = icmp eq i32 %b, 0        ; Should be dead once 'or' is simplified
+  %or.cond = or i1 %tobool, %tobool1  ; Simplifies to true
+  br i1 %or.cond, label %end, label %isfalse ; Simplifies to br label %end
+
+isfalse:             ; This block is unreachable once inlined
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  call void @dead()
+  br label %end
+
+end:
+  ret i1 %or.cond    ; Simplifies to ret i1 true
+}
+
+declare void @dead()




More information about the llvm-commits mailing list