From fe08a38a2c9e562bc18e2e93794b84fc1b31da3d Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Fri, 24 Jan 2014 06:47:57 +0000 Subject: [PATCH] [X86] Prevent the creation of redundant ops for sadd and ssub with overflow. This commit teaches the X86 backend to create the same X86 instructions when it lowers an sadd/ssub with overflow intrinsic and a conditional branch that uses that overflow result. This allows SelectionDAG to recognize and remove one of the redundant operations. This fixes and . Reviewed by Nadav git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199976 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 19 ++++++++++++-- test/CodeGen/X86/saddo-redundant-add.ll | 34 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/X86/saddo-redundant-add.ll diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 4b30ff67c9f..03eb57a4084 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -10715,11 +10715,26 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { unsigned X86Opcode; unsigned X86Cond; SDVTList VTs; + // Keep this in sync with LowerXALUO, otherwise we might create redundant + // instructions that can't be removed afterwards (i.e. X86ISD::ADD and + // X86ISD::INC). switch (CondOpcode) { case ISD::UADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_B; break; - case ISD::SADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break; + case ISD::SADDO: + if (ConstantSDNode *C = dyn_cast(RHS)) + if (C->isOne()) { + X86Opcode = X86ISD::INC; X86Cond = X86::COND_O; + break; + } + X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break; case ISD::USUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_B; break; - case ISD::SSUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break; + case ISD::SSUBO: + if (ConstantSDNode *C = dyn_cast(RHS)) + if (C->isOne()) { + X86Opcode = X86ISD::DEC; X86Cond = X86::COND_O; + break; + } + X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break; case ISD::UMULO: X86Opcode = X86ISD::UMUL; X86Cond = X86::COND_O; break; case ISD::SMULO: X86Opcode = X86ISD::SMUL; X86Cond = X86::COND_O; break; default: llvm_unreachable("unexpected overflowing operator"); diff --git a/test/CodeGen/X86/saddo-redundant-add.ll b/test/CodeGen/X86/saddo-redundant-add.ll new file mode 100644 index 00000000000..c56c68674a4 --- /dev/null +++ b/test/CodeGen/X86/saddo-redundant-add.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s + +define void @redundant_add(i64 %n) { +; Check that we don't create two additions for the sadd.with.overflow. +; CHECK-LABEL: redundant_add +; CHECK-NOT: leaq +; CHECK-NOT: addq +; CHECK: incq +; CHECK-NEXT: jno +entry: + br label %exit_check + +exit_check: + %i = phi i64 [ 0, %entry ], [ %i.next, %loop ] + %c = icmp slt i64 %i, %n + br i1 %c, label %loop, label %exit + +loop: + %i.o = tail call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %i, i64 1) + %i.next = extractvalue { i64, i1 } %i.o, 0 + %o = extractvalue { i64, i1 } %i.o, 1 + br i1 %o, label %overflow, label %exit_check + +exit: + ret void + +overflow: + tail call void @llvm.trap() + unreachable +} + +declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64) +declare void @llvm.trap() +