From 57970eb1a05646c72475881b94db9ff39a34498b Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 20 Aug 2015 23:33:34 +0000 Subject: [PATCH] AArch64: Fix cmp;ccmp ordering When producing conditional compare sequences for or operations we need to negate the operands and the finally tested flags. The thing is if we negate the finally tested flags this equals a logical negation of all previously emitted expressions. There was a case missing where we have to order OR expressions so they get emitted first. This fixes http://llvm.org/PR24459 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245641 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64ISelLowering.cpp | 13 ++++++++++--- test/CodeGen/AArch64/arm64-ccmp.ll | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 3d1235bac0a..a4b4d26a0a2 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1374,10 +1374,17 @@ static SDValue emitConjunctionDisjunctionTree(SelectionDAG &DAG, SDValue Val, if (!CanPushNegateL && !CanPushNegateR) return SDValue(); // Order the side where we can push the negate through to LHS. - if (!CanPushNegateL && CanPushNegateR) { + if (!CanPushNegateL && CanPushNegateR) + std::swap(LHS, RHS); + } else { + bool NeedsNegOutL = LHS->getOpcode() == ISD::OR; + bool NeedsNegOutR = RHS->getOpcode() == ISD::OR; + if (NeedsNegOutL && NeedsNegOutR) + return SDValue(); + // Order the side where we need to negate the output flags to RHS so it + // gets emitted first. + if (NeedsNegOutL) std::swap(LHS, RHS); - CanPushNegateL = true; - } } // Emit RHS. If we want to negate the tree we only need to push a negate diff --git a/test/CodeGen/AArch64/arm64-ccmp.ll b/test/CodeGen/AArch64/arm64-ccmp.ll index d8ad067a1bf..2f343abd2a5 100644 --- a/test/CodeGen/AArch64/arm64-ccmp.ll +++ b/test/CodeGen/AArch64/arm64-ccmp.ll @@ -337,9 +337,9 @@ define i16 @select_complicated(double %v1, double %v2, i16 %a, i16 %b) { ; CHECK-LABEL: gccbug define i64 @gccbug(i64 %x0, i64 %x1) { -; CHECK: cmp x1, #0 -; CHECK-NEXT: ccmp x0, #2, #0, eq +; CHECK: cmp x0, #2 ; CHECK-NEXT: ccmp x0, #4, #4, ne +; CHECK-NEXT: ccmp x1, #0, #0, eq ; CHECK-NEXT: orr w[[REGNUM:[0-9]+]], wzr, #0x1 ; CHECK-NEXT: cinc x0, x[[REGNUM]], eq ; CHECK-NEXT: ret @@ -373,6 +373,22 @@ define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) { ret i32 %sel } +; CHECK-LABEL: select_andor +define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) { +; CHECK: cmp w1, w2 +; CHECK-NEXT: ccmp w0, #0, #4, lt +; CHECK-NEXT: ccmp w0, w1, #0, eq +; CHECK-NEXT: csel w0, w0, w1, eq +; CHECK-NEXT: ret + %c0 = icmp eq i32 %v1, %v2 + %c1 = icmp sge i32 %v2, %v3 + %c2 = icmp eq i32 %v1, 0 + %or = or i1 %c2, %c1 + %and = and i1 %or, %c0 + %sel = select i1 %and, i32 %v1, i32 %v2 + ret i32 %sel +} + ; CHECK-LABEL: select_noccmp1 define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) { ; CHECK-NOT: CCMP -- 2.34.1