diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -315,6 +315,8 @@ LLT HalfTy, LLT ShiftAmtTy); LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -859,74 +859,9 @@ case TargetOpcode::G_FREEZE: return reduceOperationWidth(MI, TypeIdx, NarrowTy); - - case TargetOpcode::G_ADD: { - // FIXME: add support for when SizeOp0 isn't an exact multiple of - // NarrowSize. - if (SizeOp0 % NarrowSize != 0) - return UnableToLegalize; - // Expand in terms of carry-setting/consuming G_ADDE instructions. - int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); - - SmallVector Src1Regs, Src2Regs, DstRegs; - extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); - extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); - - Register CarryIn; - for (int i = 0; i < NumParts; ++i) { - Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); - Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); - - if (i == 0) - MIRBuilder.buildUAddo(DstReg, CarryOut, Src1Regs[i], Src2Regs[i]); - else { - MIRBuilder.buildUAdde(DstReg, CarryOut, Src1Regs[i], - Src2Regs[i], CarryIn); - } - - DstRegs.push_back(DstReg); - CarryIn = CarryOut; - } - Register DstReg = MI.getOperand(0).getReg(); - if(MRI.getType(DstReg).isVector()) - MIRBuilder.buildBuildVector(DstReg, DstRegs); - else - MIRBuilder.buildMerge(DstReg, DstRegs); - MI.eraseFromParent(); - return Legalized; - } - case TargetOpcode::G_SUB: { - // FIXME: add support for when SizeOp0 isn't an exact multiple of - // NarrowSize. - if (SizeOp0 % NarrowSize != 0) - return UnableToLegalize; - - int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); - - SmallVector Src1Regs, Src2Regs, DstRegs; - extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); - extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); - - Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); - Register BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); - MIRBuilder.buildInstr(TargetOpcode::G_USUBO, {DstReg, BorrowOut}, - {Src1Regs[0], Src2Regs[0]}); - DstRegs.push_back(DstReg); - Register BorrowIn = BorrowOut; - for (int i = 1; i < NumParts; ++i) { - DstReg = MRI.createGenericVirtualRegister(NarrowTy); - BorrowOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); - - MIRBuilder.buildInstr(TargetOpcode::G_USUBE, {DstReg, BorrowOut}, - {Src1Regs[i], Src2Regs[i], BorrowIn}); - - DstRegs.push_back(DstReg); - BorrowIn = BorrowOut; - } - MIRBuilder.buildMerge(MI.getOperand(0), DstRegs); - MI.eraseFromParent(); - return Legalized; - } + case TargetOpcode::G_ADD: + case TargetOpcode::G_SUB: + return narrowScalarAddSub(MI, TypeIdx, NarrowTy); case TargetOpcode::G_MUL: case TargetOpcode::G_UMULH: return narrowScalarMul(MI, NarrowTy); @@ -4506,6 +4441,67 @@ } } +LegalizerHelper::LegalizeResult +LegalizerHelper::narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy) { + if (TypeIdx != 0) + return UnableToLegalize; + + // FIXME: add support for vector types + if (MRI.getType(MI.getOperand(0).getReg()).isVector()) + return UnableToLegalize; + + uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + uint64_t NarrowSize = NarrowTy.getSizeInBits(); + + // FIXME: add support for when SizeOp0 isn't an exact multiple of + // NarrowSize. + if (SizeOp0 % NarrowSize != 0) + return UnableToLegalize; + + // Expand in terms of carry-setting/consuming G_E instructions. + int NumParts = SizeOp0 / NarrowTy.getSizeInBits(); + + unsigned OpO, OpE; + switch (MI.getOpcode()) { + case TargetOpcode::G_ADD: + OpO = TargetOpcode::G_UADDO; + OpE = TargetOpcode::G_UADDE; + break; + case TargetOpcode::G_SUB: + OpO = TargetOpcode::G_USUBO; + OpE = TargetOpcode::G_USUBE; + break; + default: + llvm_unreachable("Unexpected add/sub opcode!"); + } + + SmallVector Src1Regs, Src2Regs, DstRegs; + extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); + extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); + + Register CarryIn; + for (int i = 0; i < NumParts; ++i) { + Register DstReg = MRI.createGenericVirtualRegister(NarrowTy); + Register CarryOut = MRI.createGenericVirtualRegister(LLT::scalar(1)); + + if (i == 0) + MIRBuilder.buildInstr(OpO, {DstReg, CarryOut}, + {Src1Regs[i], Src2Regs[i]}); + else { + MIRBuilder.buildInstr(OpE, {DstReg, CarryOut}, + {Src1Regs[i], Src2Regs[i], CarryIn}); + } + + DstRegs.push_back(DstReg); + CarryIn = CarryOut; + } + Register DstReg = MI.getOperand(0).getReg(); + MIRBuilder.buildMerge(DstReg, DstRegs); + MI.eraseFromParent(); + return Legalized; +} + LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) { Register DstReg = MI.getOperand(0).getReg();