[llvm] ee6d62d - [AMDGPU] Prevent folding of the negative i32 literals as i64 (#70274)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 30 08:07:47 PDT 2023


Author: Stanislav Mekhanoshin
Date: 2023-10-30T08:07:43-07:00
New Revision: ee6d62db997bf61ef17a9f888c240f60656dc2db

URL: https://github.com/llvm/llvm-project/commit/ee6d62db997bf61ef17a9f888c240f60656dc2db
DIFF: https://github.com/llvm/llvm-project/commit/ee6d62db997bf61ef17a9f888c240f60656dc2db.diff

LOG: [AMDGPU] Prevent folding of the negative i32 literals as i64 (#70274)

We can use sign extended 64-bit literals, but only for signed operands.
At the moment we do not know if an operand is signed. Such operand will
be encoded as its low 32 bits and then either correctly sign extended or
incorrectly zero extended by HW.

Added: 
    llvm/test/CodeGen/AMDGPU/folding-of-i32-as-i64.mir

Modified: 
    llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
    llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index fae43bf30a3f6ba..f1e375ee52cb860 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -5611,9 +5611,18 @@ bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
                      OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
                      OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
                      OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32;
-    if (Is64BitOp && !AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
-        !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm()))
-      return false;
+    if (Is64BitOp &&
+        !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
+      if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp))
+        return false;
+
+      // FIXME: We can use sign extended 64-bit literals, but only for signed
+      //        operands. At the moment we do not know if an operand is signed.
+      //        Such operand will be encoded as its low 32 bits and then either
+      //        correctly sign extended or incorrectly zero extended by HW.
+      if (!Is64BitFPOp && (int32_t)Imm < 0)
+        return false;
+    }
   }
 
   // Handle non-register types that are treated like immediates.

diff  --git a/llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir b/llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir
index 6e975c8a5370758..69c6a858162f39d 100644
--- a/llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir
+++ b/llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir
@@ -84,6 +84,9 @@ body:             |
     SI_RETURN_TO_EPILOG %2
 ...
 
+# FIXME: This could be folded, but we do not know if operand of S_AND_B64 is signed or unsigned
+#        and if it will be sign or zero extended.
+
 ---
 name:            fold_uint_32bit_literal_sgpr
 tracksRegLiveness: true
@@ -92,7 +95,8 @@ body:             |
 
     ; GCN-LABEL: name: fold_uint_32bit_literal_sgpr
     ; GCN: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF
-    ; GCN-NEXT: [[S_AND_B64_:%[0-9]+]]:sreg_64 = S_AND_B64 [[DEF]], 4294967295, implicit-def $scc
+    ; GCN-NEXT: [[S_MOV_B64_:%[0-9]+]]:sreg_64 = S_MOV_B64 4294967295
+    ; GCN-NEXT: [[S_AND_B64_:%[0-9]+]]:sreg_64 = S_AND_B64 [[DEF]], [[S_MOV_B64_]], implicit-def $scc
     ; GCN-NEXT: SI_RETURN_TO_EPILOG [[S_AND_B64_]]
     %0:sreg_64 = IMPLICIT_DEF
     %1:sreg_64 = S_MOV_B64 4294967295

diff  --git a/llvm/test/CodeGen/AMDGPU/folding-of-i32-as-i64.mir b/llvm/test/CodeGen/AMDGPU/folding-of-i32-as-i64.mir
new file mode 100644
index 000000000000000..30cb88d5789fd33
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/folding-of-i32-as-i64.mir
@@ -0,0 +1,128 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+# RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -run-pass=si-fold-operands -o - %s | FileCheck -check-prefix=GCN %s
+
+# The constant is 0xffffffff80000000. It is 64-bit negative constant, but it passes the test
+# isInt<32>(). Nonetheless it is not a legal literal for a binary or unsigned operand and
+# cannot be used right in the shift as HW will zero extend it.
+
+---
+name:            imm64_shift_int32_const_0xffffffff80000000
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0xffffffff80000000
+    ; GCN: [[S_MOV_B:%[0-9]+]]:sreg_64 = S_MOV_B64_IMM_PSEUDO -2147483648
+    ; GCN-NEXT: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 [[S_MOV_B]], 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 18446744071562067968
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_shift_int32_const_0xffffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0xffffffff
+    ; GCN: [[S_MOV_B:%[0-9]+]]:sreg_64 = S_MOV_B64_IMM_PSEUDO 4294967295
+    ; GCN-NEXT: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 [[S_MOV_B]], 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 4294967295
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_shift_int32_const_0x80000000
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0x80000000
+    ; GCN: [[S_MOV_B:%[0-9]+]]:sreg_64 = S_MOV_B64_IMM_PSEUDO 2147483648
+    ; GCN-NEXT: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 [[S_MOV_B]], 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 2147483648
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_shift_int32_const_0x7fffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0x7fffffff
+    ; GCN: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 2147483647, 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 2147483647
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_shift_int32_const_0x1ffffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0x1ffffffff
+    ; GCN: [[S_MOV_B:%[0-9]+]]:sreg_64 = S_MOV_B64_IMM_PSEUDO 8589934591
+    ; GCN-NEXT: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 [[S_MOV_B]], 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 8589934591
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_shift_int32_const_0xffffffffffffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_shift_int32_const_0xffffffffffffffff
+    ; GCN: [[S_LSHL_B64_:%[0-9]+]]:sreg_64 = S_LSHL_B64 -1, 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_LSHL_B64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO -1
+    %1:sreg_64 = S_LSHL_B64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_ashr_int32_const_0xffffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_ashr_int32_const_0xffffffff
+    ; GCN: [[S_MOV_B:%[0-9]+]]:sreg_64 = S_MOV_B64_IMM_PSEUDO 4294967295
+    ; GCN-NEXT: [[S_ASHR_I64_:%[0-9]+]]:sreg_64 = S_ASHR_I64 [[S_MOV_B]], 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_ASHR_I64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 4294967295
+    %1:sreg_64 = S_ASHR_I64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_ashr_int32_const_0x7fffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_ashr_int32_const_0x7fffffff
+    ; GCN: [[S_ASHR_I64_:%[0-9]+]]:sreg_64 = S_ASHR_I64 2147483647, 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_ASHR_I64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO 2147483647
+    %1:sreg_64 = S_ASHR_I64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...
+
+---
+name:            imm64_ashr_int32_const_0xffffffffffffffff
+body: |
+  bb.0:
+    ; GCN-LABEL: name: imm64_ashr_int32_const_0xffffffffffffffff
+    ; GCN: [[S_ASHR_I64_:%[0-9]+]]:sreg_64 = S_ASHR_I64 -1, 1, implicit-def $scc
+    ; GCN-NEXT: S_ENDPGM 0, implicit [[S_ASHR_I64_]]
+    %0:sreg_64 = S_MOV_B64_IMM_PSEUDO -1
+    %1:sreg_64 = S_ASHR_I64 %0, 1, implicit-def $scc
+    S_ENDPGM 0, implicit %1
+
+...


        


More information about the llvm-commits mailing list