[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