Unverified Commit ee6d62db authored by Stanislav Mekhanoshin's avatar Stanislav Mekhanoshin Committed by GitHub
Browse files

[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.
parent 273ceb13
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -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()))
    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.
+5 −1
Original line number Diff line number Diff line
@@ -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
+128 −0
Original line number Diff line number Diff line
# 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

...