From 979aca08775cdabb49e5573fe52c4cb893d67fb8 Mon Sep 17 00:00:00 2001 From: Rose Date: Sat, 21 Jun 2025 15:05:23 -0400 Subject: [PATCH 1/2] Pre-commit test (NFC) --- llvm/test/CodeGen/AArch64/instruct-neg.ll | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/instruct-neg.ll diff --git a/llvm/test/CodeGen/AArch64/instruct-neg.ll b/llvm/test/CodeGen/AArch64/instruct-neg.ll new file mode 100644 index 0000000000000..1edce89fb7d90 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/instruct-neg.ll @@ -0,0 +1,12 @@ +; 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: mov w8, wzr +; CHECK-NEXT: sub w0, w8, w0 +; CHECK-NEXT: ret + %sub = sub nsw i32 0, %b + ret i32 %sub +} From c865723cee3e7a463ba687efff1ae995e05ec889 Mon Sep 17 00:00:00 2001 From: Rose Date: Sat, 21 Jun 2025 15:36:00 -0400 Subject: [PATCH 2/2] [AArch64] Have isel just do neg directly This means we do not have to rely on register coalescing to fix this, which matches gcc outputting things like neg on -O0 --- llvm/lib/Target/AArch64/AArch64FastISel.cpp | 13 +++++++++++++ llvm/test/CodeGen/AArch64/instruct-neg.ll | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) 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 index 1edce89fb7d90..4d60fb768901e 100644 --- a/llvm/test/CodeGen/AArch64/instruct-neg.ll +++ b/llvm/test/CodeGen/AArch64/instruct-neg.ll @@ -4,8 +4,7 @@ define i32 @negb(i32 %b) { ; CHECK-LABEL: negb: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, wzr -; CHECK-NEXT: sub w0, w8, w0 +; CHECK-NEXT: neg w0, w0 ; CHECK-NEXT: ret %sub = sub nsw i32 0, %b ret i32 %sub