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,27 @@ 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 &TRI = TII->getRegisterInfo(); + + // Fine if the operand can be encoded as an inline constant + if (!(OpToFold->isImm() && TII->isInlineConstant(*OpToFold, OpInfo) && + TRI.opCanUseInlineConstant(OpInfo.OperandType))) { + // Otherwise check for another constant + for (unsigned i = 0, e = InstDesc.getNumOperands(); i != e; ++i) { + auto &Op = MI->getOperand(i); + if (OpNo != i && !Op.isReg() && Op.isImm() && + !TII->isInlineConstant(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,25 @@ +# 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 +...