summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2016-08-19 17:17:06 +0000
committerTim Northover <tnorthover@apple.com>2016-08-19 17:17:06 +0000
commit91c8173093b35392e804a7267c386d147e73979e (patch)
tree7aecf6871f63e6a6afc21a9e3c23d9e3e896fe27 /llvm/lib/CodeGen
parent170dede75dc30599b1628e83ad45ec940b165af3 (diff)
downloadbcm5719-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.cpp38
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp24
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp16
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;
}
OpenPOWER on IntegriCloud