diff options
author | Tim Northover <tnorthover@apple.com> | 2016-08-19 17:17:06 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2016-08-19 17:17:06 +0000 |
commit | 91c8173093b35392e804a7267c386d147e73979e (patch) | |
tree | 7aecf6871f63e6a6afc21a9e3c23d9e3e896fe27 /llvm/lib/CodeGen | |
parent | 170dede75dc30599b1628e83ad45ec940b165af3 (diff) | |
download | bcm5719-llvm-91c8173093b35392e804a7267c386d147e73979e.tar.gz bcm5719-llvm-91c8173093b35392e804a7267c386d147e73979e.zip |
GlobalISel: support overflow arithmetic intrinsics.
Unsigned addition and subtraction can reuse the instructions created to
legalize large width operations (i.e. both produce and consume a carry flag).
Signed operations and multiplies get a dedicated op-with-overflow instruction.
Once this is produced the two values are combined into a struct register (which
will almost always be merged with a corresponding G_EXTRACT as part of
legalization).
llvm-svn: 279278
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp | 16 |
3 files changed, 63 insertions, 15 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index a7b6d20c212..ac95b8262d9 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -204,6 +204,41 @@ bool IRTranslator::translateCast(unsigned Opcode, const User &U) { return true; } +bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, + Intrinsic::ID ID) { + unsigned Op = 0; + switch (ID) { + default: return false; + case Intrinsic::uadd_with_overflow: Op = TargetOpcode::G_UADDE; break; + case Intrinsic::sadd_with_overflow: Op = TargetOpcode::G_SADDO; break; + case Intrinsic::usub_with_overflow: Op = TargetOpcode::G_USUBE; break; + case Intrinsic::ssub_with_overflow: Op = TargetOpcode::G_SSUBO; break; + case Intrinsic::umul_with_overflow: Op = TargetOpcode::G_UMULO; break; + case Intrinsic::smul_with_overflow: Op = TargetOpcode::G_SMULO; break; + } + + LLT Ty{*CI.getOperand(0)->getType()}; + LLT s1 = LLT::scalar(1); + unsigned Width = Ty.getSizeInBits(); + unsigned Res = MRI->createGenericVirtualRegister(Width); + unsigned Overflow = MRI->createGenericVirtualRegister(1); + auto MIB = MIRBuilder.buildInstr(Op, {Ty, s1}) + .addDef(Res) + .addDef(Overflow) + .addUse(getOrCreateVReg(*CI.getOperand(0))) + .addUse(getOrCreateVReg(*CI.getOperand(1))); + + if (Op == TargetOpcode::G_UADDE || Op == TargetOpcode::G_USUBE) { + unsigned Zero = MRI->createGenericVirtualRegister(1); + EntryBuilder.buildConstant(s1, Zero, 0); + MIB.addUse(Zero); + } + + MIRBuilder.buildSequence(LLT{*CI.getType(), DL}, getOrCreateVReg(CI), Res, 0, + Overflow, Width); + return true; +} + bool IRTranslator::translateCall(const User &U) { const CallInst &CI = cast<CallInst>(U); auto TII = MIRBuilder.getMF().getTarget().getIntrinsicInfo(); @@ -227,6 +262,9 @@ bool IRTranslator::translateCall(const User &U) { assert(ID != Intrinsic::not_intrinsic && "unknown intrinsic"); + if (translateKnownIntrinsic(CI, ID)) + return true; + // Need types (starting with return) & args. SmallVector<LLT, 4> Tys; Tys.emplace_back(*CI.getType()); diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 70a24415f1d..92dbab05e03 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -124,11 +124,11 @@ MachineInstrBuilder MachineIRBuilder::buildStore(LLT VTy, LLT PTy, .addMemOperand(&MMO); } -MachineInstrBuilder MachineIRBuilder::buildAdde(LLT Ty, unsigned Res, - unsigned CarryOut, unsigned Op0, - unsigned Op1, - unsigned CarryIn) { - return buildInstr(TargetOpcode::G_ADDE, Ty) +MachineInstrBuilder MachineIRBuilder::buildUAdde(LLT Ty, unsigned Res, + unsigned CarryOut, + unsigned Op0, unsigned Op1, + unsigned CarryIn) { + return buildInstr(TargetOpcode::G_UADDE, Ty) .addDef(Res) .addDef(CarryOut) .addUse(Op0) @@ -157,12 +157,18 @@ MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src, return MIB; } -MachineInstrBuilder MachineIRBuilder::buildSequence(LLT Ty, unsigned Res, - ArrayRef<unsigned> Ops) { +MachineInstrBuilder +MachineIRBuilder::buildSequence(LLT Ty, unsigned Res, + ArrayRef<unsigned> Ops, + ArrayRef<unsigned> Indexes) { + assert(Ops.size() == Indexes.size() && "incompatible args"); + MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE, Ty); MIB.addDef(Res); - for (auto Op : Ops) - MIB.addUse(Op); + for (unsigned i = 0; i < Ops.size(); ++i) { + MIB.addUse(Ops[i]); + MIB.addImm(Indexes[i]); + } return MIB; } diff --git a/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp index 01d87d1e70d..d999fbe8892 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp @@ -71,7 +71,7 @@ MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) { MIRBuilder.setInstr(MI); - SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; + SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes; extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); @@ -82,13 +82,15 @@ MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) { unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize); unsigned CarryOut = MRI.createGenericVirtualRegister(1); - MIRBuilder.buildAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i], Src2Regs[i], - CarryIn); + MIRBuilder.buildUAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i], + Src2Regs[i], CarryIn); DstRegs.push_back(DstReg); + Indexes.push_back(i * NarrowSize); CarryIn = CarryOut; } - MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs); + MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs, + Indexes); MI.eraseFromParent(); return Legalized; } @@ -140,7 +142,7 @@ MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, LLT NarrowTy) { MIRBuilder.setInstr(MI); - SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs; + SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs, Indexes; extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs); extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs); @@ -148,9 +150,11 @@ MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, LLT NarrowTy) { unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize); MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]); DstRegs.push_back(DstReg); + Indexes.push_back(i * NarrowSize); } - MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs); + MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs, + Indexes); MI.eraseFromParent(); return Legalized; } |