[llvm] [x86][GlobalISel] Select MOV32ri64 for unsigned 32-bit i64 constants (PR #185182)

Levi Laine via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 19:05:22 PDT 2026


https://github.com/levish0 updated https://github.com/llvm/llvm-project/pull/185182

>From 49857ea436372dc6b3cca7c064d15cbf91a31ec7 Mon Sep 17 00:00:00 2001
From: levish0 <shiueo.csh at gmail.com>
Date: Sat, 7 Mar 2026 21:13:04 +0900
Subject: [PATCH 1/2] [x86][GlobalISel] Select MOV32ri64 for unsigned 32-bit
 i64 constants

Make X86 GlobalISel to select MOV32ri64 for i64 constants that fit in an                                                                                                                                                                                                 unsigned 32-bit immediate.

GlobalISel currently only distinguishes between signed 32-bit immediates                                                                                                                                                                                                   (MOV64ri32) and larger 64-bit immediates (MOV64ri), even though FastISel                                                                                                                                                                                                   already uses MOV32ri64 for zero-extended 32-bit values.
---
 .../X86/GISel/X86InstructionSelector.cpp      |  5 ++--
 .../X86/GlobalISel/select-constant.mir        | 26 +++++++++++++++++--
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index bbc7f464eda4a..d9830e93f0c1f 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -823,8 +823,9 @@ bool X86InstructionSelector::selectConstant(MachineInstr &I,
     NewOpc = X86::MOV32ri;
     break;
   case 64:
-    // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
-    if (isInt<32>(Val))
+    if (isUInt<32>(Val))
+      NewOpc = X86::MOV32ri64;
+    else if (isInt<32>(Val))
       NewOpc = X86::MOV64ri32;
     else
       NewOpc = X86::MOV64ri;
diff --git a/llvm/test/CodeGen/X86/GlobalISel/select-constant.mir b/llvm/test/CodeGen/X86/GlobalISel/select-constant.mir
index eef6ba61e5591..adb80c93952f5 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/select-constant.mir
+++ b/llvm/test/CodeGen/X86/GlobalISel/select-constant.mir
@@ -26,6 +26,10 @@
     ret i64 1879048192
   }
 
+  define i64 @const_i64_u32_max() {
+    ret i64 4294967295
+  }
+
   define i64 @const_i64_i32() {
     ret i64 -1
   }
@@ -143,6 +147,24 @@ body:             |
     $rax = COPY %0(s64)
     RET 0, implicit $rax
 
+...
+---
+name:            const_i64_u32_max
+legalized:       true
+regBankSelected: true
+selected:        false
+registers:
+  - { id: 0, class: gpr }
+body:             |
+  bb.1 (%ir-block.0):
+    ; CHECK-LABEL: name: const_i64_u32_max
+    ; CHECK: [[MOV32ri64_:%[0-9]+]]:gr64 = MOV32ri64 4294967295
+    ; CHECK-NEXT: $rax = COPY [[MOV32ri64_]]
+    ; CHECK-NEXT: RET 0, implicit $rax
+    %0(s64) = G_CONSTANT i64 4294967295
+    $rax = COPY %0(s64)
+    RET 0, implicit $rax
+
 ...
 ---
 name:            const_i64_i32
@@ -178,8 +200,8 @@ body:             |
     ; CHECK: liveins: $rdi
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
-    ; CHECK-NEXT: [[MOV64ri32_:%[0-9]+]]:gr64 = MOV64ri32 0
-    ; CHECK-NEXT: MOV64mr [[COPY]], 1, $noreg, 0, $noreg, [[MOV64ri32_]] :: (store (p0) into %ir.data)
+    ; CHECK-NEXT: [[MOV32ri64_:%[0-9]+]]:gr64 = MOV32ri64 0
+    ; CHECK-NEXT: MOV64mr [[COPY]], 1, $noreg, 0, $noreg, [[MOV32ri64_]] :: (store (p0) into %ir.data)
     ; CHECK-NEXT: RET 0
     %0(p0) = COPY $rdi
     %1(p0) = G_CONSTANT i64 0

>From 9ab2307fbd2bdd629bc10c0f2d318beb98cc5fcb Mon Sep 17 00:00:00 2001
From: levish0 <shiueo.csh at gmail.com>
Date: Sat, 7 Mar 2026 22:15:42 +0900
Subject: [PATCH 2/2] Update constant.ll checks for unsigned i64 constants

---
 llvm/test/CodeGen/X86/GlobalISel/constant.ll | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/GlobalISel/constant.ll b/llvm/test/CodeGen/X86/GlobalISel/constant.ll
index 0ef0270cf3dfc..ac80b546cb330 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/constant.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/constant.ll
@@ -42,6 +42,15 @@ define i64 @const_i64_u32() {
   ret i64 1879048192
 }
 
+;i64 value fits into u32 but not i32
+define i64 @const_i64_u32_max() {
+; CHECK-LABEL: const_i64_u32_max:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
+; CHECK-NEXT:    retq
+  ret i64 4294967295
+}
+
 ;i64 value fit into i32
 define i64 @const_i64_i32() {
 ; CHECK-LABEL: const_i64_i32:
@@ -54,7 +63,7 @@ define i64 @const_i64_i32() {
 define void @main(ptr %data) {
 ; CHECK-LABEL: main:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq $0, %rax
+; CHECK-NEXT:    movl $0, %eax
 ; CHECK-NEXT:    movq %rax, (%rdi)
 ; CHECK-NEXT:    retq
   store ptr null, ptr %data, align 8



More information about the llvm-commits mailing list