forked from OSchip/llvm-project
[CodeGenPrepare] Refine the cost model provided by the promotion helper.
- Use TargetLowering to check for the actual cost of each extension. - Provide a factorized method to check for the cost of an extension: TargetLowering::isExtFree. - Provide a virtual method TargetLowering::isExtFreeImpl for targets to be able to tune the cost of non-free extensions. This refactoring offers a better granularity to model what really happens on different targets. No performance changes and very few code differences. Part of <rdar://problem/19267165> llvm-svn: 231855
This commit is contained in:
parent
4bb90a71de
commit
1b274f99ad
|
@ -1484,6 +1484,33 @@ public:
|
||||||
|
|
||||||
virtual bool isProfitableToHoist(Instruction *I) const { return true; }
|
virtual bool isProfitableToHoist(Instruction *I) const { return true; }
|
||||||
|
|
||||||
|
/// Return true if the extension represented by \p I is free.
|
||||||
|
/// Unlikely the is[Z|FP]ExtFree family which is based on types,
|
||||||
|
/// this method can use the context provided by \p I to decide
|
||||||
|
/// whether or not \p I is free.
|
||||||
|
/// This method extends the behavior of the is[Z|FP]ExtFree family.
|
||||||
|
/// In other words, if is[Z|FP]Free returns true, then this method
|
||||||
|
/// returns true as well. The converse is not true.
|
||||||
|
/// The target can perform the adequate checks by overriding isExtFreeImpl.
|
||||||
|
/// \pre \p I must be a sign, zero, or fp extension.
|
||||||
|
bool isExtFree(const Instruction *I) const {
|
||||||
|
switch (I->getOpcode()) {
|
||||||
|
case Instruction::FPExt:
|
||||||
|
if (isFPExtFree(EVT::getEVT(I->getType())))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case Instruction::ZExt:
|
||||||
|
if (isZExtFree(I->getOperand(0)->getType(), I->getType()))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case Instruction::SExt:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Instruction is not an extension");
|
||||||
|
}
|
||||||
|
return isExtFreeImpl(I);
|
||||||
|
}
|
||||||
|
|
||||||
/// Return true if any actual instruction that defines a value of type Ty1
|
/// Return true if any actual instruction that defines a value of type Ty1
|
||||||
/// implicitly zero-extends the value to Ty2 in the result register.
|
/// implicitly zero-extends the value to Ty2 in the result register.
|
||||||
///
|
///
|
||||||
|
@ -1847,6 +1874,11 @@ private:
|
||||||
CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL];
|
CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL];
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/// Return true if the extension represented by \p I is free.
|
||||||
|
/// \pre \p I is a sign, zero, or fp extension and
|
||||||
|
/// is[Z|FP]ExtFree of the related types is not true.
|
||||||
|
virtual bool isExtFreeImpl(const Instruction *I) const { return false; }
|
||||||
|
|
||||||
/// \brief Specify maximum number of store instructions per memset call.
|
/// \brief Specify maximum number of store instructions per memset call.
|
||||||
///
|
///
|
||||||
/// When lowering \@llvm.memset this field specifies the maximum number of
|
/// When lowering \@llvm.memset this field specifies the maximum number of
|
||||||
|
|
|
@ -186,7 +186,7 @@ class TypePromotionTransaction;
|
||||||
bool ExtLdPromotion(TypePromotionTransaction &TPT, LoadInst *&LI,
|
bool ExtLdPromotion(TypePromotionTransaction &TPT, LoadInst *&LI,
|
||||||
Instruction *&Inst,
|
Instruction *&Inst,
|
||||||
const SmallVectorImpl<Instruction *> &Exts,
|
const SmallVectorImpl<Instruction *> &Exts,
|
||||||
unsigned CreatedInst);
|
unsigned CreatedInstCost);
|
||||||
bool splitBranchCondition(Function &F);
|
bool splitBranchCondition(Function &F);
|
||||||
bool simplifyOffsetableRelocate(Instruction &I);
|
bool simplifyOffsetableRelocate(Instruction &I);
|
||||||
};
|
};
|
||||||
|
@ -2023,7 +2023,7 @@ private:
|
||||||
ExtAddrMode &AMBefore,
|
ExtAddrMode &AMBefore,
|
||||||
ExtAddrMode &AMAfter);
|
ExtAddrMode &AMAfter);
|
||||||
bool ValueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2);
|
bool ValueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2);
|
||||||
bool IsPromotionProfitable(unsigned MatchedSize, unsigned SizeWithPromotion,
|
bool IsPromotionProfitable(unsigned NewCost, unsigned OldCost,
|
||||||
Value *PromotedOperand) const;
|
Value *PromotedOperand) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2157,7 +2157,7 @@ class TypePromotionHelper {
|
||||||
/// \brief Utility function to promote the operand of \p Ext when this
|
/// \brief Utility function to promote the operand of \p Ext when this
|
||||||
/// operand is a promotable trunc or sext or zext.
|
/// operand is a promotable trunc or sext or zext.
|
||||||
/// \p PromotedInsts maps the instructions to their type before promotion.
|
/// \p PromotedInsts maps the instructions to their type before promotion.
|
||||||
/// \p CreatedInsts[out] contains how many non-free instructions have been
|
/// \p CreatedInstsCost[out] contains the cost of all instructions
|
||||||
/// created to promote the operand of Ext.
|
/// created to promote the operand of Ext.
|
||||||
/// Newly added extensions are inserted in \p Exts.
|
/// Newly added extensions are inserted in \p Exts.
|
||||||
/// Newly added truncates are inserted in \p Truncs.
|
/// Newly added truncates are inserted in \p Truncs.
|
||||||
|
@ -2165,53 +2165,55 @@ class TypePromotionHelper {
|
||||||
/// \return The promoted value which is used instead of Ext.
|
/// \return The promoted value which is used instead of Ext.
|
||||||
static Value *promoteOperandForTruncAndAnyExt(
|
static Value *promoteOperandForTruncAndAnyExt(
|
||||||
Instruction *Ext, TypePromotionTransaction &TPT,
|
Instruction *Ext, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts,
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Truncs);
|
SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI);
|
||||||
|
|
||||||
/// \brief Utility function to promote the operand of \p Ext when this
|
/// \brief Utility function to promote the operand of \p Ext when this
|
||||||
/// operand is promotable and is not a supported trunc or sext.
|
/// operand is promotable and is not a supported trunc or sext.
|
||||||
/// \p PromotedInsts maps the instructions to their type before promotion.
|
/// \p PromotedInsts maps the instructions to their type before promotion.
|
||||||
/// \p CreatedInsts[out] contains how many non-free instructions have been
|
/// \p CreatedInstsCost[out] contains the cost of all the instructions
|
||||||
/// created to promote the operand of Ext.
|
/// created to promote the operand of Ext.
|
||||||
/// Newly added extensions are inserted in \p Exts.
|
/// Newly added extensions are inserted in \p Exts.
|
||||||
/// Newly added truncates are inserted in \p Truncs.
|
/// Newly added truncates are inserted in \p Truncs.
|
||||||
/// Should never be called directly.
|
/// Should never be called directly.
|
||||||
/// \return The promoted value which is used instead of Ext.
|
/// \return The promoted value which is used instead of Ext.
|
||||||
static Value *
|
static Value *promoteOperandForOther(Instruction *Ext,
|
||||||
promoteOperandForOther(Instruction *Ext, TypePromotionTransaction &TPT,
|
TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts,
|
InstrToOrigTy &PromotedInsts,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
unsigned &CreatedInstsCost,
|
||||||
SmallVectorImpl<Instruction *> *Truncs, bool IsSExt);
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
|
SmallVectorImpl<Instruction *> *Truncs,
|
||||||
|
const TargetLowering &TLI, bool IsSExt);
|
||||||
|
|
||||||
/// \see promoteOperandForOther.
|
/// \see promoteOperandForOther.
|
||||||
static Value *
|
static Value *signExtendOperandForOther(
|
||||||
signExtendOperandForOther(Instruction *Ext, TypePromotionTransaction &TPT,
|
Instruction *Ext, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts,
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
|
||||||
unsigned &CreatedInsts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
|
||||||
SmallVectorImpl<Instruction *> *Truncs) {
|
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
|
||||||
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInsts, Exts,
|
Exts, Truncs, TLI, true);
|
||||||
Truncs, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \see promoteOperandForOther.
|
/// \see promoteOperandForOther.
|
||||||
static Value *
|
static Value *zeroExtendOperandForOther(
|
||||||
zeroExtendOperandForOther(Instruction *Ext, TypePromotionTransaction &TPT,
|
Instruction *Ext, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts,
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
|
||||||
unsigned &CreatedInsts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
|
||||||
SmallVectorImpl<Instruction *> *Truncs) {
|
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInstsCost,
|
||||||
return promoteOperandForOther(Ext, TPT, PromotedInsts, CreatedInsts, Exts,
|
Exts, Truncs, TLI, false);
|
||||||
Truncs, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Type for the utility function that promotes the operand of Ext.
|
/// Type for the utility function that promotes the operand of Ext.
|
||||||
typedef Value *(*Action)(Instruction *Ext, TypePromotionTransaction &TPT,
|
typedef Value *(*Action)(Instruction *Ext, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts,
|
InstrToOrigTy &PromotedInsts,
|
||||||
|
unsigned &CreatedInstsCost,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Truncs);
|
SmallVectorImpl<Instruction *> *Truncs,
|
||||||
|
const TargetLowering &TLI);
|
||||||
/// \brief Given a sign/zero extend instruction \p Ext, return the approriate
|
/// \brief Given a sign/zero extend instruction \p Ext, return the approriate
|
||||||
/// action to promote the operand of \p Ext instead of using Ext.
|
/// action to promote the operand of \p Ext instead of using Ext.
|
||||||
/// \return NULL if no promotable action is possible with the current
|
/// \return NULL if no promotable action is possible with the current
|
||||||
|
@ -2328,16 +2330,18 @@ TypePromotionHelper::Action TypePromotionHelper::getAction(
|
||||||
|
|
||||||
Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||||
llvm::Instruction *SExt, TypePromotionTransaction &TPT,
|
llvm::Instruction *SExt, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts,
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Truncs) {
|
SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI) {
|
||||||
// By construction, the operand of SExt is an instruction. Otherwise we cannot
|
// By construction, the operand of SExt is an instruction. Otherwise we cannot
|
||||||
// get through it and this method should not be called.
|
// get through it and this method should not be called.
|
||||||
Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
|
Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
|
||||||
Value *ExtVal = SExt;
|
Value *ExtVal = SExt;
|
||||||
|
bool HasMergedNonFreeExt = false;
|
||||||
if (isa<ZExtInst>(SExtOpnd)) {
|
if (isa<ZExtInst>(SExtOpnd)) {
|
||||||
// Replace s|zext(zext(opnd))
|
// Replace s|zext(zext(opnd))
|
||||||
// => zext(opnd).
|
// => zext(opnd).
|
||||||
|
HasMergedNonFreeExt = !TLI.isExtFree(SExtOpnd);
|
||||||
Value *ZExt =
|
Value *ZExt =
|
||||||
TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType());
|
TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType());
|
||||||
TPT.replaceAllUsesWith(SExt, ZExt);
|
TPT.replaceAllUsesWith(SExt, ZExt);
|
||||||
|
@ -2348,7 +2352,7 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||||
// => z|sext(opnd).
|
// => z|sext(opnd).
|
||||||
TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
|
TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
|
||||||
}
|
}
|
||||||
CreatedInsts = 0;
|
CreatedInstsCost = 0;
|
||||||
|
|
||||||
// Remove dead code.
|
// Remove dead code.
|
||||||
if (SExtOpnd->use_empty())
|
if (SExtOpnd->use_empty())
|
||||||
|
@ -2357,8 +2361,11 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||||
// Check if the extension is still needed.
|
// Check if the extension is still needed.
|
||||||
Instruction *ExtInst = dyn_cast<Instruction>(ExtVal);
|
Instruction *ExtInst = dyn_cast<Instruction>(ExtVal);
|
||||||
if (!ExtInst || ExtInst->getType() != ExtInst->getOperand(0)->getType()) {
|
if (!ExtInst || ExtInst->getType() != ExtInst->getOperand(0)->getType()) {
|
||||||
if (ExtInst && Exts)
|
if (ExtInst) {
|
||||||
Exts->push_back(ExtInst);
|
if (Exts)
|
||||||
|
Exts->push_back(ExtInst);
|
||||||
|
CreatedInstsCost = !TLI.isExtFree(ExtInst) && !HasMergedNonFreeExt;
|
||||||
|
}
|
||||||
return ExtVal;
|
return ExtVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2371,13 +2378,14 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||||
|
|
||||||
Value *TypePromotionHelper::promoteOperandForOther(
|
Value *TypePromotionHelper::promoteOperandForOther(
|
||||||
Instruction *Ext, TypePromotionTransaction &TPT,
|
Instruction *Ext, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts,
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInstsCost,
|
||||||
SmallVectorImpl<Instruction *> *Exts,
|
SmallVectorImpl<Instruction *> *Exts,
|
||||||
SmallVectorImpl<Instruction *> *Truncs, bool IsSExt) {
|
SmallVectorImpl<Instruction *> *Truncs, const TargetLowering &TLI,
|
||||||
|
bool IsSExt) {
|
||||||
// By construction, the operand of Ext is an instruction. Otherwise we cannot
|
// By construction, the operand of Ext is an instruction. Otherwise we cannot
|
||||||
// get through it and this method should not be called.
|
// get through it and this method should not be called.
|
||||||
Instruction *ExtOpnd = cast<Instruction>(Ext->getOperand(0));
|
Instruction *ExtOpnd = cast<Instruction>(Ext->getOperand(0));
|
||||||
CreatedInsts = 0;
|
CreatedInstsCost = 0;
|
||||||
if (!ExtOpnd->hasOneUse()) {
|
if (!ExtOpnd->hasOneUse()) {
|
||||||
// ExtOpnd will be promoted.
|
// ExtOpnd will be promoted.
|
||||||
// All its uses, but Ext, will need to use a truncated value of the
|
// All its uses, but Ext, will need to use a truncated value of the
|
||||||
|
@ -2452,7 +2460,6 @@ Value *TypePromotionHelper::promoteOperandForOther(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ExtForOpnd = cast<Instruction>(ValForExtOpnd);
|
ExtForOpnd = cast<Instruction>(ValForExtOpnd);
|
||||||
++CreatedInsts;
|
|
||||||
}
|
}
|
||||||
if (Exts)
|
if (Exts)
|
||||||
Exts->push_back(ExtForOpnd);
|
Exts->push_back(ExtForOpnd);
|
||||||
|
@ -2461,6 +2468,7 @@ Value *TypePromotionHelper::promoteOperandForOther(
|
||||||
// Move the sign extension before the insertion point.
|
// Move the sign extension before the insertion point.
|
||||||
TPT.moveBefore(ExtForOpnd, ExtOpnd);
|
TPT.moveBefore(ExtForOpnd, ExtOpnd);
|
||||||
TPT.setOperand(ExtOpnd, OpIdx, ExtForOpnd);
|
TPT.setOperand(ExtOpnd, OpIdx, ExtForOpnd);
|
||||||
|
CreatedInstsCost += !TLI.isExtFree(ExtForOpnd);
|
||||||
// If more sext are required, new instructions will have to be created.
|
// If more sext are required, new instructions will have to be created.
|
||||||
ExtForOpnd = nullptr;
|
ExtForOpnd = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -2473,22 +2481,22 @@ Value *TypePromotionHelper::promoteOperandForOther(
|
||||||
|
|
||||||
/// IsPromotionProfitable - Check whether or not promoting an instruction
|
/// IsPromotionProfitable - Check whether or not promoting an instruction
|
||||||
/// to a wider type was profitable.
|
/// to a wider type was profitable.
|
||||||
/// \p MatchedSize gives the number of instructions that have been matched
|
/// \p NewCost gives the cost of extension instructions created by the
|
||||||
/// in the addressing mode after the promotion was applied.
|
/// promotion.
|
||||||
/// \p SizeWithPromotion gives the number of created instructions for
|
/// \p OldCost gives the cost of extension instructions before the promotion
|
||||||
/// the promotion plus the number of instructions that have been
|
/// plus the number of instructions that have been
|
||||||
/// matched in the addressing mode before the promotion.
|
/// matched in the addressing mode the promotion.
|
||||||
/// \p PromotedOperand is the value that has been promoted.
|
/// \p PromotedOperand is the value that has been promoted.
|
||||||
/// \return True if the promotion is profitable, false otherwise.
|
/// \return True if the promotion is profitable, false otherwise.
|
||||||
bool
|
bool AddressingModeMatcher::IsPromotionProfitable(
|
||||||
AddressingModeMatcher::IsPromotionProfitable(unsigned MatchedSize,
|
unsigned NewCost, unsigned OldCost, Value *PromotedOperand) const {
|
||||||
unsigned SizeWithPromotion,
|
DEBUG(dbgs() << "OldCost: " << OldCost << "\tNewCost: " << NewCost << '\n');
|
||||||
Value *PromotedOperand) const {
|
// The cost of the new extensions is greater than the cost of the
|
||||||
// We folded less instructions than what we created to promote the operand.
|
// old extension plus what we folded.
|
||||||
// This is not profitable.
|
// This is not profitable.
|
||||||
if (MatchedSize < SizeWithPromotion)
|
if (NewCost > OldCost)
|
||||||
return false;
|
return false;
|
||||||
if (MatchedSize > SizeWithPromotion)
|
if (NewCost < OldCost)
|
||||||
return true;
|
return true;
|
||||||
// The promotion is neutral but it may help folding the sign extension in
|
// The promotion is neutral but it may help folding the sign extension in
|
||||||
// loads for instance.
|
// loads for instance.
|
||||||
|
@ -2686,9 +2694,10 @@ bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode,
|
||||||
|
|
||||||
TypePromotionTransaction::ConstRestorationPt LastKnownGood =
|
TypePromotionTransaction::ConstRestorationPt LastKnownGood =
|
||||||
TPT.getRestorationPoint();
|
TPT.getRestorationPoint();
|
||||||
unsigned CreatedInsts = 0;
|
unsigned CreatedInstsCost = 0;
|
||||||
|
unsigned ExtCost = !TLI.isExtFree(Ext);
|
||||||
Value *PromotedOperand =
|
Value *PromotedOperand =
|
||||||
TPH(Ext, TPT, PromotedInsts, CreatedInsts, nullptr, nullptr);
|
TPH(Ext, TPT, PromotedInsts, CreatedInstsCost, nullptr, nullptr, TLI);
|
||||||
// SExt has been moved away.
|
// SExt has been moved away.
|
||||||
// Thus either it will be rematched later in the recursive calls or it is
|
// Thus either it will be rematched later in the recursive calls or it is
|
||||||
// gone. Anyway, we must not fold it into the addressing mode at this point.
|
// gone. Anyway, we must not fold it into the addressing mode at this point.
|
||||||
|
@ -2710,7 +2719,12 @@ bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode,
|
||||||
unsigned OldSize = AddrModeInsts.size();
|
unsigned OldSize = AddrModeInsts.size();
|
||||||
|
|
||||||
if (!MatchAddr(PromotedOperand, Depth) ||
|
if (!MatchAddr(PromotedOperand, Depth) ||
|
||||||
!IsPromotionProfitable(AddrModeInsts.size(), OldSize + CreatedInsts,
|
// The total of the new cost is equals to the cost of the created
|
||||||
|
// instructions.
|
||||||
|
// The total of the old cost is equals to the cost of the extension plus
|
||||||
|
// what we have saved in the addressing mode.
|
||||||
|
!IsPromotionProfitable(CreatedInstsCost,
|
||||||
|
ExtCost + (AddrModeInsts.size() - OldSize),
|
||||||
PromotedOperand)) {
|
PromotedOperand)) {
|
||||||
AddrMode = BackupAddrMode;
|
AddrMode = BackupAddrMode;
|
||||||
AddrModeInsts.resize(OldSize);
|
AddrModeInsts.resize(OldSize);
|
||||||
|
@ -3470,7 +3484,7 @@ static bool hasSameExtUse(Instruction *Inst, const TargetLowering &TLI) {
|
||||||
bool CodeGenPrepare::ExtLdPromotion(TypePromotionTransaction &TPT,
|
bool CodeGenPrepare::ExtLdPromotion(TypePromotionTransaction &TPT,
|
||||||
LoadInst *&LI, Instruction *&Inst,
|
LoadInst *&LI, Instruction *&Inst,
|
||||||
const SmallVectorImpl<Instruction *> &Exts,
|
const SmallVectorImpl<Instruction *> &Exts,
|
||||||
unsigned CreatedInsts = 0) {
|
unsigned CreatedInstsCost = 0) {
|
||||||
// Iterate over all the extensions to see if one form an ext(load).
|
// Iterate over all the extensions to see if one form an ext(load).
|
||||||
for (auto I : Exts) {
|
for (auto I : Exts) {
|
||||||
// Check if we directly have ext(load).
|
// Check if we directly have ext(load).
|
||||||
|
@ -3492,10 +3506,11 @@ bool CodeGenPrepare::ExtLdPromotion(TypePromotionTransaction &TPT,
|
||||||
TypePromotionTransaction::ConstRestorationPt LastKnownGood =
|
TypePromotionTransaction::ConstRestorationPt LastKnownGood =
|
||||||
TPT.getRestorationPoint();
|
TPT.getRestorationPoint();
|
||||||
SmallVector<Instruction *, 4> NewExts;
|
SmallVector<Instruction *, 4> NewExts;
|
||||||
unsigned NewCreatedInsts = 0;
|
unsigned NewCreatedInstsCost = 0;
|
||||||
|
unsigned ExtCost = !TLI->isExtFree(I);
|
||||||
// Promote.
|
// Promote.
|
||||||
Value *PromotedVal =
|
Value *PromotedVal = TPH(I, TPT, PromotedInsts, NewCreatedInstsCost,
|
||||||
TPH(I, TPT, PromotedInsts, NewCreatedInsts, &NewExts, nullptr);
|
&NewExts, nullptr, *TLI);
|
||||||
assert(PromotedVal &&
|
assert(PromotedVal &&
|
||||||
"TypePromotionHelper should have filtered out those cases");
|
"TypePromotionHelper should have filtered out those cases");
|
||||||
|
|
||||||
|
@ -3505,9 +3520,10 @@ bool CodeGenPrepare::ExtLdPromotion(TypePromotionTransaction &TPT,
|
||||||
// With exactly 2, the transformation is neutral, because we will merge
|
// With exactly 2, the transformation is neutral, because we will merge
|
||||||
// one extension but leave one. However, we optimistically keep going,
|
// one extension but leave one. However, we optimistically keep going,
|
||||||
// because the new extension may be removed too.
|
// because the new extension may be removed too.
|
||||||
unsigned TotalCreatedInsts = CreatedInsts + NewCreatedInsts;
|
long long TotalCreatedInstsCost = CreatedInstsCost + NewCreatedInstsCost;
|
||||||
|
TotalCreatedInstsCost -= ExtCost;
|
||||||
if (!StressExtLdPromotion &&
|
if (!StressExtLdPromotion &&
|
||||||
(TotalCreatedInsts > 1 ||
|
(TotalCreatedInstsCost > 1 ||
|
||||||
!isPromotedInstructionLegal(*TLI, PromotedVal))) {
|
!isPromotedInstructionLegal(*TLI, PromotedVal))) {
|
||||||
// The promotion is not profitable, rollback to the previous state.
|
// The promotion is not profitable, rollback to the previous state.
|
||||||
TPT.rollback(LastKnownGood);
|
TPT.rollback(LastKnownGood);
|
||||||
|
@ -3515,8 +3531,8 @@ bool CodeGenPrepare::ExtLdPromotion(TypePromotionTransaction &TPT,
|
||||||
}
|
}
|
||||||
// The promotion is profitable.
|
// The promotion is profitable.
|
||||||
// Check if it exposes an ext(load).
|
// Check if it exposes an ext(load).
|
||||||
(void)ExtLdPromotion(TPT, LI, Inst, NewExts, TotalCreatedInsts);
|
(void)ExtLdPromotion(TPT, LI, Inst, NewExts, TotalCreatedInstsCost);
|
||||||
if (LI && (StressExtLdPromotion || NewCreatedInsts == 0 ||
|
if (LI && (StressExtLdPromotion || NewCreatedInstsCost <= ExtCost ||
|
||||||
// If we have created a new extension, i.e., now we have two
|
// If we have created a new extension, i.e., now we have two
|
||||||
// extensions. We must make sure one of them is merged with
|
// extensions. We must make sure one of them is merged with
|
||||||
// the load, otherwise we may degrade the code quality.
|
// the load, otherwise we may degrade the code quality.
|
||||||
|
|
|
@ -90,9 +90,7 @@ define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) {
|
||||||
; rolled back.
|
; rolled back.
|
||||||
; Still, this test case exercises the desired code path.
|
; Still, this test case exercises the desired code path.
|
||||||
; CHECK-LABEL: @oneArgPromotionCstZExt
|
; CHECK-LABEL: @oneArgPromotionCstZExt
|
||||||
; CHECK: [[ZEXT:%[a-zA-Z_0-9-]+]] = zext i16 undef to i32
|
; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 0, 1
|
||||||
; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ZEXT]] to i64
|
|
||||||
; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXT]], 1
|
|
||||||
; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
|
; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
|
||||||
; CHECK: ret
|
; CHECK: ret
|
||||||
define i8 @oneArgPromotionCstZExt(i8* %base) {
|
define i8 @oneArgPromotionCstZExt(i8* %base) {
|
||||||
|
|
|
@ -361,3 +361,34 @@ entry:
|
||||||
%conv3 = sext i16 %add to i32
|
%conv3 = sext i16 %add to i32
|
||||||
ret i32 %conv3
|
ret i32 %conv3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that we see that one zext can be derived from the other for free.
|
||||||
|
; OPTALL-LABEL: @promoteTwoArgZextWithSourceExtendedTwice
|
||||||
|
; OPTALL: [[LD:%[a-zA-Z_0-9-]+]] = load i8, i8* %p
|
||||||
|
|
||||||
|
; OPT-NEXT: [[ZEXT64:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i64
|
||||||
|
; OPT-NEXT: [[ZEXT32:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i32
|
||||||
|
; OPT-NEXT: [[RES32:%[a-zA-Z_0-9-]+]] = add nuw i32 [[ZEXT32]], %b
|
||||||
|
; OPT-NEXT: [[RES64:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ZEXT64]], 12
|
||||||
|
; OPT-NEXT: store i32 [[RES32]], i32* %addr
|
||||||
|
; OPT-NEXT: store i64 [[RES64]], i64* %q
|
||||||
|
;
|
||||||
|
; DISABLE-NEXT: [[ZEXT32:%[a-zA-Z_0-9-]+]] = zext i8 [[LD]] to i32
|
||||||
|
; DISABLE-NEXT: [[RES32:%[a-zA-Z_0-9-]+]] = add nuw i32 [[ZEXT32]], %b
|
||||||
|
; DISABLE-NEXT: [[RES2_32:%[a-zA-Z_0-9-]+]] = add nuw i32 [[ZEXT32]], 12
|
||||||
|
; DISABLE-NEXT: store i32 [[RES32]], i32* %addr
|
||||||
|
; DISABLE-NEXT: [[ZEXT64:%[a-zA-Z_0-9-]+]] = zext i32 [[RES2_32]] to i64
|
||||||
|
; DISABLE-NEXT: store i64 [[ZEXT64]], i64* %q
|
||||||
|
;
|
||||||
|
; OPTALL-NEXT: ret void
|
||||||
|
define void @promoteTwoArgZextWithSourceExtendedTwice(i8* %p, i64* %q, i32 %b, i32* %addr) {
|
||||||
|
entry:
|
||||||
|
%t = load i8, i8* %p
|
||||||
|
%zextt = zext i8 %t to i32
|
||||||
|
%add = add nuw i32 %zextt, %b
|
||||||
|
%add2 = add nuw i32 %zextt, 12
|
||||||
|
store i32 %add, i32 *%addr
|
||||||
|
%s = zext i32 %add2 to i64
|
||||||
|
store i64 %s, i64* %q
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue