summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp134
1 files changed, 73 insertions, 61 deletions
diff --git a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp b/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
index 0bd1f9ca639..06949bea70a 100644
--- a/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
+++ b/llvm/lib/Target/ARM/ARMCodeGenPrepare.cpp
@@ -126,7 +126,7 @@ class IRPromoter {
SmallPtrSetImpl<Instruction*> &SafeToPromote);
void TruncateSinks(SmallPtrSetImpl<Value*> &Sources,
SmallPtrSetImpl<Instruction*> &Sinks);
- void Cleanup(SmallPtrSetImpl<Instruction*> &Sinks);
+ void Cleanup(SmallPtrSetImpl<Value*> &Visited);
public:
IRPromoter(Module *M) : M(M), Ctx(M->getContext()),
@@ -180,6 +180,18 @@ static bool generateSignBits(Value *V) {
Opc == Instruction::SRem;
}
+static bool EqualTypeSize(Value *V) {
+ return V->getType()->getScalarSizeInBits() == ARMCodeGenPrepare::TypeSize;
+}
+
+static bool LessOrEqualTypeSize(Value *V) {
+ return V->getType()->getScalarSizeInBits() <= ARMCodeGenPrepare::TypeSize;
+}
+
+static bool GreaterThanTypeSize(Value *V) {
+ return V->getType()->getScalarSizeInBits() > ARMCodeGenPrepare::TypeSize;
+}
+
/// Some instructions can use 8- and 16-bit operands, and we don't need to
/// promote anything larger. We disallow booleans to make life easier when
/// dealing with icmps but allow any other integer that is <= 16 bits. Void
@@ -194,11 +206,10 @@ static bool isSupportedType(Value *V) {
if (auto *Ld = dyn_cast<LoadInst>(V))
Ty = cast<PointerType>(Ld->getPointerOperandType())->getElementType();
- const IntegerType *IntTy = dyn_cast<IntegerType>(Ty);
- if (!IntTy)
+ if (!isa<IntegerType>(Ty))
return false;
- return IntTy->getBitWidth() == ARMCodeGenPrepare::TypeSize;
+ return LessOrEqualTypeSize(V);
}
/// Return true if the given value is a source in the use-def chain, producing
@@ -221,7 +232,7 @@ static bool isSource(Value *V) {
else if (auto *Call = dyn_cast<CallInst>(V))
return Call->hasRetAttr(Attribute::AttrKind::ZExt);
else if (auto *Trunc = dyn_cast<TruncInst>(V))
- return isSupportedType(Trunc);
+ return EqualTypeSize(Trunc);
return false;
}
@@ -232,18 +243,15 @@ static bool isSink(Value *V) {
// TODO The truncate also isn't actually necessary because we would already
// proved that the data value is kept within the range of the original data
// type.
- auto UsesNarrowValue = [](Value *V) {
- return V->getType()->getScalarSizeInBits() == ARMCodeGenPrepare::TypeSize;
- };
if (auto *Store = dyn_cast<StoreInst>(V))
- return UsesNarrowValue(Store->getValueOperand());
+ return LessOrEqualTypeSize(Store->getValueOperand());
if (auto *Return = dyn_cast<ReturnInst>(V))
- return UsesNarrowValue(Return->getReturnValue());
+ return LessOrEqualTypeSize(Return->getReturnValue());
if (auto *Trunc = dyn_cast<TruncInst>(V))
- return UsesNarrowValue(Trunc->getOperand(0));
+ return EqualTypeSize(Trunc->getOperand(0));
if (auto *ZExt = dyn_cast<ZExtInst>(V))
- return UsesNarrowValue(ZExt->getOperand(0));
+ return GreaterThanTypeSize(ZExt);
if (auto *ICmp = dyn_cast<ICmpInst>(V))
return ICmp->isSigned();
@@ -649,36 +657,37 @@ 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;
+void IRPromoter::Cleanup(SmallPtrSetImpl<Value*> &Visited) {
+ // Some zexts will now have become redundant, along with their trunc
+ // operands, so remove them
+ for (auto V : Visited) {
+ if (!isa<ZExtInst>(V))
+ 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;
- }
+ auto ZExt = cast<ZExtInst>(V);
+ if (ZExt->getDestTy() != ExtTy)
+ 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);
- }
+ Value *Src = ZExt->getOperand(0);
+ if (ZExt->getSrcTy() == ZExt->getDestTy()) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: Removing unnecessary cast.\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);
}
}
@@ -728,18 +737,9 @@ void IRPromoter::Mutate(Type *OrigTy,
// Finally, remove unecessary zexts and truncs, delete old instructions and
// clear the data structures.
- Cleanup(Sinks);
+ Cleanup(Visited);
- LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete:\n");
- LLVM_DEBUG(dbgs();
- for (auto *V : Sources)
- V->dump();
- for (auto *I : NewInsts)
- I->dump();
- for (auto *V : Visited) {
- if (!Sources.count(V))
- V->dump();
- });
+ LLVM_DEBUG(dbgs() << "ARM CGP: Mutation complete\n");
}
/// We accept most instructions, as well as Arguments and ConstantInsts. We
@@ -747,8 +747,15 @@ void IRPromoter::Mutate(Type *OrigTy,
/// return value is zeroext. We don't allow opcodes that can introduce sign
/// bits.
bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
- if (isa<ICmpInst>(V))
- return true;
+ if (auto *I = dyn_cast<ICmpInst>(V)) {
+ // Now that we allow small types than TypeSize, only allow icmp of
+ // TypeSize because they will require a trunc to be legalised.
+ // TODO: Allow icmp of smaller types, and calculate at the end
+ // whether the transform would be beneficial.
+ if (isa<PointerType>(I->getOperand(0)->getType()))
+ return true;
+ return EqualTypeSize(I->getOperand(0));
+ }
// Memory instructions
if (isa<StoreInst>(V) || isa<GetElementPtrInst>(V))
@@ -766,12 +773,11 @@ bool ARMCodeGenPrepare::isSupportedValue(Value *V) {
isa<LoadInst>(V))
return isSupportedType(V);
- // Truncs can be either sources or sinks.
- if (auto *Trunc = dyn_cast<TruncInst>(V))
- return isSupportedType(Trunc) || isSupportedType(Trunc->getOperand(0));
+ if (isa<SExtInst>(V))
+ return false;
- if (isa<CastInst>(V) && !isa<SExtInst>(V))
- return isSupportedType(cast<CastInst>(V)->getOperand(0));
+ if (auto *Cast = dyn_cast<CastInst>(V))
+ return isSupportedType(Cast) || isSupportedType(Cast->getOperand(0));
// Special cases for calls as we need to check for zeroext
// TODO We should accept calls even if they don't have zeroext, as they can
@@ -901,13 +907,17 @@ bool ARMCodeGenPrepare::TryToPromote(Value *V) {
// Calls can be both sources and sinks.
if (isSink(V))
Sinks.insert(cast<Instruction>(V));
+
if (isSource(V))
Sources.insert(V);
- else if (auto *I = dyn_cast<Instruction>(V)) {
- // Visit operands of any instruction visited.
- for (auto &U : I->operands()) {
- if (!AddLegalInst(U))
- return false;
+
+ if (!isSink(V) && !isSource(V)) {
+ if (auto *I = dyn_cast<Instruction>(V)) {
+ // Visit operands of any instruction visited.
+ for (auto &U : I->operands()) {
+ if (!AddLegalInst(U))
+ return false;
+ }
}
}
@@ -973,6 +983,8 @@ bool ARMCodeGenPrepare::runOnFunction(Function &F) {
if (CI.isSigned() || !isa<IntegerType>(CI.getOperand(0)->getType()))
continue;
+ LLVM_DEBUG(dbgs() << "ARM CGP: Searching from: " << CI << "\n");
+
for (auto &Op : CI.operands()) {
if (auto *I = dyn_cast<Instruction>(Op))
MadeChange |= TryToPromote(I);
OpenPOWER on IntegriCloud