summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp101
1 files changed, 68 insertions, 33 deletions
diff --git a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp b/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
index 0a6ea9dc325..8a7555bb95c 100644
--- a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
+++ b/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
@@ -114,8 +114,8 @@ class IRPromoter {
SmallPtrSet<Value*, 8> Promoted;
Module *M = nullptr;
LLVMContext &Ctx;
- Type *ExtTy = nullptr;
- Type *OrigTy = nullptr;
+ IntegerType *ExtTy = nullptr;
+ IntegerType *OrigTy = nullptr;
void PrepareConstants(SmallPtrSetImpl<Value*> &Visited,
SmallPtrSetImpl<Instruction*> &SafeToPromote);
@@ -126,20 +126,12 @@ class IRPromoter {
SmallPtrSetImpl<Instruction*> &SafeToPromote);
void TruncateSinks(SmallPtrSetImpl<Value*> &Sources,
SmallPtrSetImpl<Instruction*> &Sinks);
+ void Cleanup(SmallPtrSetImpl<Instruction*> &Sinks);
public:
IRPromoter(Module *M) : M(M), Ctx(M->getContext()),
ExtTy(Type::getInt32Ty(Ctx)) { }
- void Cleanup() {
- for (auto *I : InstsToRemove) {
- LLVM_DEBUG(dbgs() << "ARM CGP: Removing " << *I << "\n");
- I->dropAllReferences();
- I->eraseFromParent();
- }
- InstsToRemove.clear();
- NewInsts.clear();
- }
void Mutate(Type *OrigTy,
SmallPtrSetImpl<Value*> &Visited,
@@ -401,17 +393,7 @@ static bool isPromotedResultSafe(Value *V) {
if (generateSignBits(V))
return false;
- // If I is only being used by something that will require its value to be
- // truncated, then we don't care about the promoted result.
- auto *I = cast<Instruction>(V);
- if (I->hasOneUse() && isSink(*I->use_begin())) {
- LLVM_DEBUG(dbgs() << "ARM CGP: Only use is a sink: " << *V << "\n");
- return true;
- }
-
- if (isa<OverflowingBinaryOperator>(I))
- return false;
- return true;
+ return !isa<OverflowingBinaryOperator>(V);
}
/// Return the intrinsic for the instruction that can perform the same
@@ -514,21 +496,24 @@ void IRPromoter::ExtendSources(SmallPtrSetImpl<Value*> &Sources) {
IRBuilder<> Builder{Ctx};
auto InsertZExt = [&](Value *V, Instruction *InsertPt) {
+ assert(V->getType() != ExtTy && "zext already extends to i32");
LLVM_DEBUG(dbgs() << "ARM CGP: Inserting ZExt for " << *V << "\n");
Builder.SetInsertPoint(InsertPt);
if (auto *I = dyn_cast<Instruction>(V))
Builder.SetCurrentDebugLocation(I->getDebugLoc());
- auto *ZExt = cast<Instruction>(Builder.CreateZExt(V, ExtTy));
- if (isa<Argument>(V))
- ZExt->moveBefore(InsertPt);
- else
- ZExt->moveAfter(InsertPt);
+
+ Value *ZExt = Builder.CreateZExt(V, ExtTy);
+ if (auto *I = dyn_cast<Instruction>(ZExt)) {
+ if (isa<Argument>(V))
+ I->moveBefore(InsertPt);
+ else
+ I->moveAfter(InsertPt);
+ NewInsts.insert(I);
+ }
ReplaceAllUsersOfWith(V, ZExt);
- NewInsts.insert(ZExt);
TruncTysMap[ZExt] = TruncTysMap[V];
};
-
// Now, insert extending instructions between the sources and their users.
LLVM_DEBUG(dbgs() << "ARM CGP: Promoting sources:\n");
for (auto V : Sources) {
@@ -664,6 +649,49 @@ void IRPromoter::TruncateSinks(SmallPtrSetImpl<Value*> &Sources,
}
}
}
+
+}
+
+void IRPromoter::Cleanup(SmallPtrSetImpl<Instruction*> &Sinks) {
+ // Some zext sinks will now have become redundant, along with their trunc
+ // operands, so remove them.
+ for (auto I : Sinks) {
+ if (auto *ZExt = dyn_cast<ZExtInst>(I)) {
+ if (ZExt->getDestTy() != ExtTy)
+ continue;
+
+ Value *Src = ZExt->getOperand(0);
+ if (ZExt->getSrcTy() == ZExt->getDestTy()) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Removing unnecessary zext\n");
+ ReplaceAllUsersOfWith(ZExt, Src);
+ InstsToRemove.push_back(ZExt);
+ continue;
+ }
+
+ // For any truncs that we insert to handle zexts, we can replace the
+ // result of the zext with the input to the trunc.
+ if (NewInsts.count(Src) && isa<TruncInst>(Src)) {
+ auto *Trunc = cast<TruncInst>(Src);
+ assert(Trunc->getOperand(0)->getType() == ExtTy &&
+ "expected inserted trunc to be operating on i32");
+ LLVM_DEBUG(dbgs() << "ARM CGP: Replacing zext with trunc operand: "
+ << *Trunc->getOperand(0));
+ ReplaceAllUsersOfWith(ZExt, Trunc->getOperand(0));
+ InstsToRemove.push_back(ZExt);
+ }
+ }
+ }
+
+ for (auto *I : InstsToRemove) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Removing " << *I << "\n");
+ I->dropAllReferences();
+ I->eraseFromParent();
+ }
+
+ InstsToRemove.clear();
+ NewInsts.clear();
+ TruncTysMap.clear();
+ Promoted.clear();
}
void IRPromoter::Mutate(Type *OrigTy,
@@ -673,7 +701,11 @@ void IRPromoter::Mutate(Type *OrigTy,
SmallPtrSetImpl<Instruction*> &SafeToPromote) {
LLVM_DEBUG(dbgs() << "ARM CGP: Promoting use-def chains to from "
<< ARMCodeGenPrepare::TypeSize << " to 32-bits\n");
- this->OrigTy = OrigTy;
+
+ assert(isa<IntegerType>(OrigTy) && "expected integer type");
+ this->OrigTy = cast<IntegerType>(OrigTy);
+ assert(OrigTy->getPrimitiveSizeInBits() < ExtTy->getPrimitiveSizeInBits() &&
+ "original type not smaller than extended type");
// Cache original types.
for (auto *V : Visited)
@@ -691,9 +723,13 @@ void IRPromoter::Mutate(Type *OrigTy,
// promote.
PromoteTree(Visited, Sources, Sinks, SafeToPromote);
- // Finally, insert trunc instructions for use by calls, stores etc...
+ // Insert trunc instructions for use by calls, stores etc...
TruncateSinks(Sources, Sinks);
+ // Finally, remove unecessary zexts and truncs, delete old instructions and
+ // clear the data structures.
+ Cleanup(Sinks);
+
LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete:\n");
LLVM_DEBUG(dbgs();
for (auto *V : Sources)
@@ -943,9 +979,8 @@ bool ARMCodeGenPrepare::runOnFunction(Function &F) {
}
}
}
- Promoter->Cleanup();
LLVM_DEBUG(if (verifyFunction(F, &dbgs())) {
- dbgs();
+ dbgs() << F;
report_fatal_error("Broken function after type promotion");
});
}
OpenPOWER on IntegriCloud