diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp --- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -429,6 +429,29 @@ return true; } + // Check the case where we might introduce a second constant operand to a + // scalar instruction + if (TII->isSALU(MI->getOpcode())) { + const MCInstrDesc &InstDesc = MI->getDesc(); + const MCOperandInfo &OpInfo = InstDesc.OpInfo[OpNo]; + const SIRegisterInfo &SRI = TII->getRegisterInfo(); + + // Fine if the operand can be encoded as an inline constant + if (OpToFold->isImm()) { + if (!SRI.opCanUseInlineConstant(OpInfo.OperandType) || + !TII->isInlineConstant(*OpToFold, OpInfo)) { + // Otherwise check for another constant + for (unsigned i = 0, e = InstDesc.getNumOperands(); i != e; ++i) { + auto &Op = MI->getOperand(i); + if (OpNo != i && + TII->isLiteralConstantLike(Op, OpInfo)) { + return false; + } + } + } + } + } + appendFoldCandidate(FoldList, MI, OpNo, OpToFold); return true; } diff --git a/llvm/test/CodeGen/AMDGPU/fold-sgpr-multi-imm.mir b/llvm/test/CodeGen/AMDGPU/fold-sgpr-multi-imm.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/fold-sgpr-multi-imm.mir @@ -0,0 +1,71 @@ +# RUN: llc -march=amdgcn -verify-machineinstrs -run-pass si-fold-operands %s -o - | FileCheck -check-prefix=GCN %s + +# GCN-LABEL: name: test_part_fold{{$}} +# GCN: %2:sreg_32 = S_ADD_I32 70, %1 +--- +name: test_part_fold +tracksRegLiveness: true +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 70 + %1:sreg_32 = S_MOV_B32 80 + %2:sreg_32 = S_ADD_I32 %0, %1, implicit-def $scc +... + +# GCN-LABEL: name: test_inline_const{{$}} +# GCN: %2:sreg_32 = S_ADD_I32 70, 63 +--- +name: test_inline_const +tracksRegLiveness: true +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 70 + %1:sreg_32 = S_MOV_B32 63 + %2:sreg_32 = S_ADD_I32 %0, %1, implicit-def $scc +... +# GCN-LABEL: name: test_obscure{{$}} +# GCN: %2:sreg_32 = S_LSHL2_ADD_U32 70, %1 +--- +name: test_obscure +tracksRegLiveness: true +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 70 + %1:sreg_32 = S_MOV_B32 80 + %2:sreg_32 = S_LSHL2_ADD_U32 %0, %1, implicit-def $scc +... +# GCN-LABEL: name: test_obscure_inline{{$}} +# GCN: %2:sreg_32 = S_LSHL2_ADD_U32 70, 63 +--- +name: test_obscure_inline +tracksRegLiveness: true +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 70 + %1:sreg_32 = S_MOV_B32 63 + %2:sreg_32 = S_LSHL2_ADD_U32 %0, %1, implicit-def $scc +... +# GCN-LABEL: name: test_frameindex{{$}} +# GCN: %1:sreg_32 = S_ADD_I32 %stack.0, %0 +--- +name: test_frameindex +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16} +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 70 + %1:sreg_32 = S_ADD_I32 %stack.0, %0, implicit-def $scc +... +# GCN-LABEL: name: test_frameindex_inline{{$}} +# GCN: %1:sreg_32 = S_ADD_I32 %stack.0, 63 +--- +name: test_frameindex_inline +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16} +body: | + bb.0: + %0:sreg_32 = S_MOV_B32 63 + %1:sreg_32 = S_ADD_I32 %stack.0, %0, implicit-def $scc +...