[llvm] [X86] Truncate i64 add/sub/mul arithmetic to i32 with known zeros in upper 32 bits (PR #143313)
Omkar Mohanty via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 9 03:55:45 PDT 2025
https://github.com/omkar-mohanty updated https://github.com/llvm/llvm-project/pull/143313
>From 966b560c88eef73cc398c425fd3927f0e02b9e21 Mon Sep 17 00:00:00 2001
From: omkar-mohanty <franzohouser at gmail.com>
Date: Mon, 9 Jun 2025 13:13:18 +0530
Subject: [PATCH] [X86] Reduce i64 to i32 when upper 33 bits are known zeros
for add
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 20 ++++++++++++++++
llvm/test/CodeGen/X86/reduce-i64-add.ll | 31 +++++++++++++++++++++++++
2 files changed, 51 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/reduce-i64-add.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b59d4a8618220..1728024f83455 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58070,8 +58070,28 @@ static SDValue combineAdd(SDNode *N, SelectionDAG &DAG,
EVT VT = N->getValueType(0);
SDValue Op0 = N->getOperand(0);
SDValue Op1 = N->getOperand(1);
+ unsigned int Opcode = N->getOpcode();
SDLoc DL(N);
+ // Use a 32-bit add+zext if upper 33 bits known zero.
+ if (VT == MVT::i64 && Subtarget.is64Bit()) {
+ APInt HiMask = APInt::getHighBitsSet(64, 33);
+ if (DAG.MaskedValueIsZero(Op0, HiMask)
+&& DAG.MaskedValueIsZero(Op1, HiMask)) {
+ SDValue LHS = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op0);
+ SDValue RHS = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op1);
+ bool NSW = Op0->getFlags().hasNoSignedWrap();
+ bool NUW = Op0->getFlags().hasNoUnsignedWrap();
+ NSW = NSW & DAG.willNotOverflowAdd(true, LHS, RHS);
+ NUW = NUW & DAG.willNotOverflowAdd(false, LHS, RHS);
+ SDNodeFlags Flags;
+ Flags.setNoUnsignedWrap(NUW);
+ Flags.setNoSignedWrap(NSW);
+ SDValue Sum = DAG.getNode(Opcode, DL, MVT::i32, LHS, RHS, Flags);
+ return DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Sum);
+ }
+ }
+
if (SDValue Select = pushAddIntoCmovOfConsts(N, DL, DAG, Subtarget))
return Select;
diff --git a/llvm/test/CodeGen/X86/reduce-i64-add.ll b/llvm/test/CodeGen/X86/reduce-i64-add.ll
new file mode 100644
index 0000000000000..a9399a0dd26eb
--- /dev/null
+++ b/llvm/test/CodeGen/X86/reduce-i64-add.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s --check-prefix=X64-LINUX
+; RUN: llc < %s -mtriple=x86_64-win32 | FileCheck %s --check-prefix=X64-WIN32
+
+define i64 @test1(i16 %x) nounwind {
+; X86-LABEL: test1:
+; X86: # %bb.0: # %entry
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl $42, %eax
+; X86-NEXT: movzwl %ax, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LINUX-LABEL: test1:
+; X64-LINUX: # %bb.0: # %entry
+; X64-LINUX-NEXT: addl $42, %edi
+; X64-LINUX-NEXT: movzwl %di, %eax
+; X64-LINUX-NEXT: retq
+;
+; X64-WIN32-LABEL: test1:
+; X64-WIN32: # %bb.0: # %entry
+; X64-WIN32-NEXT: # kill: def $cx killed $cx def $ecx
+; X64-WIN32-NEXT: addl $42, %ecx
+; X64-WIN32-NEXT: movzwl %cx, %eax
+; X64-WIN32-NEXT: retq
+entry:
+ %add = add nuw nsw i16 %x, 42
+ %conv = zext i16 %add to i64
+ ret i64 %conv
+}
More information about the llvm-commits
mailing list