Skip to content

[AMDGPU] Prevent folding of the negative i32 literals as i64 #70274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5497,9 +5497,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.
Expand Down
6 changes: 5 additions & 1 deletion llvm/test/CodeGen/AMDGPU/fold-short-64-bit-literals.mir
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
128 changes: 128 additions & 0 deletions llvm/test/CodeGen/AMDGPU/folding-of-i32-as-i64.mir
Original file line number Diff line number Diff line change
@@ -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

...