diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 9d74bb5a8661d..c3a20c7e9b5b8 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -1201,6 +1201,19 @@ Register AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS, SI->getOpcode() == Instruction::AShr ) std::swap(LHS, RHS); + // Special case: sub 0, x -> neg x (use zero register directly) + if (!UseAdd && isa(LHS) && cast(LHS)->isNullValue()) { + Register RHSReg = getRegForValue(RHS); + if (!RHSReg) + return Register(); + + if (NeedExtend) + RHSReg = emitIntExt(SrcVT, RHSReg, RetVT, IsZExt); + + Register ZeroReg = RetVT == MVT::i64 ? AArch64::XZR : AArch64::WZR; + return emitAddSub_rr(UseAdd, RetVT, ZeroReg, RHSReg, SetFlags, WantResult); + } + Register LHSReg = getRegForValue(LHS); if (!LHSReg) return Register(); diff --git a/llvm/test/CodeGen/AArch64/instruct-neg.ll b/llvm/test/CodeGen/AArch64/instruct-neg.ll new file mode 100644 index 0000000000000..4d60fb768901e --- /dev/null +++ b/llvm/test/CodeGen/AArch64/instruct-neg.ll @@ -0,0 +1,11 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64-linux-gnu -O0 -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK + +define i32 @negb(i32 %b) { +; CHECK-LABEL: negb: +; CHECK: // %bb.0: +; CHECK-NEXT: neg w0, w0 +; CHECK-NEXT: ret + %sub = sub nsw i32 0, %b + ret i32 %sub +}