[PATCH][AArch64] Enable sign check optimization by CSE
Sergey Dmitrouk
sdmitrouk at accesssoftek.com
Wed Jul 23 08:54:06 PDT 2014
Hi,
Basing on the following information from [this post][0] by James Molloy:
2. "if (a < 0 && b == c || a > 0 && b == d)" - the first comparison of
'a' against zero is done twice, when the flag results of the first
comparison could be used for the second comparison.
I've made a patch (attached) that removes this extra comparison. More
complex cases like comparisons with non-zero immediate values or with
registers doesn't seem to be task for a code generator. Comparing with
zero is quite common, so I seems to be worth adding.
Please review the patch. Couldn't find a better place to make the
change, but I'll be happy to adjust the patch if anyone has better ideas.
Best regards,
Sergey
0: http://article.gmane.org/gmane.comp.compilers.llvm.devel/74269
-------------- next part --------------
[AArch64] Enable sign check optimization by CSE
Turn "x > 1" condition into "x >= 0" to make both "x < 0" and "x > 0"
checks generate the same code. This allows CSE pass to remove
duplicated compare instructions in this quite common branching case.
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp
index 4921826..5367817 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2949,6 +2949,18 @@ SDValue AArch64TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
}
}
+ // Turn "x > 1" condition into "x >= 0" to make both "x < 0" and "x > 0"
+ // checks generate the same code. This allows CSE pass to remove duplicated
+ // compare instructions in this quite common branching case.
+ if (RHSC && RHSC->isOne() && CC == ISD::SETLT) {
+ CC = ISD::SETLE;
+
+ uint64_t C = RHSC->getZExtValue();
+ C = (RHS.getValueType() == MVT::i32) ? (uint32_t)(C - 1) : (C - 1);
+
+ RHS = DAG.getConstant(C, RHS.getValueType());
+ }
+
SDValue CCVal;
SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, dl);
return DAG.getNode(AArch64ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
diff --git a/test/CodeGen/AArch64/combine-sign-comparisons-by-cse.ll b/test/CodeGen/AArch64/combine-sign-comparisons-by-cse.ll
new file mode 100644
index 0000000..aa74be9
--- /dev/null
+++ b/test/CodeGen/AArch64/combine-sign-comparisons-by-cse.ll
@@ -0,0 +1,39 @@
+; RUN: llc < %s -march=aarch64 -mtriple=aarch64-linux-gnu | FileCheck %s
+
+; marked as external to prevent possible optimizations
+ at a = external global i32
+ at b = external global i32
+ at c = external global i32
+ at d = external global i32
+
+define void @combine-sign-comparisons-by-cse() {
+; CHECK-LABEL: %lor.lhs.false
+; CHECK-NEXT: b.l
+entry:
+ %0 = load i32* @a, align 4
+ %cmp = icmp slt i32 %0, 0
+ br i1 %cmp, label %land.lhs.true, label %lor.lhs.false
+
+land.lhs.true:
+ %1 = load i32* @b, align 4
+ %2 = load i32* @c, align 4
+ %cmp1 = icmp eq i32 %1, %2
+ br i1 %cmp1, label %return, label %if.end
+
+lor.lhs.false:
+ %cmp2 = icmp sgt i32 %0, 0
+ br i1 %cmp2, label %land.lhs.true3, label %if.end
+
+land.lhs.true3:
+ %3 = load i32* @b, align 4
+ %4 = load i32* @d, align 4
+ %cmp4 = icmp eq i32 %3, %4
+ br i1 %cmp4, label %return, label %if.end
+
+if.end:
+ br label %return
+
+return:
+ %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ]
+ ret void
+}
More information about the llvm-commits
mailing list