aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/TypePromotion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/TypePromotion.cpp')
-rw-r--r--llvm/lib/CodeGen/TypePromotion.cpp152
1 files changed, 50 insertions, 102 deletions
diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp
index 2ce6ea1d4212..d042deefd746 100644
--- a/llvm/lib/CodeGen/TypePromotion.cpp
+++ b/llvm/lib/CodeGen/TypePromotion.cpp
@@ -108,7 +108,7 @@ class IRPromoter {
SetVector<Value*> &Visited;
SetVector<Value*> &Sources;
SetVector<Instruction*> &Sinks;
- SmallVectorImpl<Instruction*> &SafeWrap;
+ SmallPtrSetImpl<Instruction *> &SafeWrap;
IntegerType *ExtTy = nullptr;
SmallPtrSet<Value*, 8> NewInsts;
SmallPtrSet<Instruction*, 4> InstsToRemove;
@@ -116,7 +116,6 @@ class IRPromoter {
SmallPtrSet<Value*, 8> Promoted;
void ReplaceAllUsersOfWith(Value *From, Value *To);
- void PrepareWrappingAdds(void);
void ExtendSources(void);
void ConvertTruncs(void);
void PromoteTree(void);
@@ -125,11 +124,11 @@ class IRPromoter {
public:
IRPromoter(LLVMContext &C, IntegerType *Ty, unsigned Width,
- SetVector<Value*> &visited, SetVector<Value*> &sources,
- SetVector<Instruction*> &sinks,
- SmallVectorImpl<Instruction*> &wrap) :
- Ctx(C), OrigTy(Ty), PromotedWidth(Width), Visited(visited),
- Sources(sources), Sinks(sinks), SafeWrap(wrap) {
+ SetVector<Value *> &visited, SetVector<Value *> &sources,
+ SetVector<Instruction *> &sinks,
+ SmallPtrSetImpl<Instruction *> &wrap)
+ : Ctx(C), OrigTy(Ty), PromotedWidth(Width), Visited(visited),
+ Sources(sources), Sinks(sinks), SafeWrap(wrap) {
ExtTy = IntegerType::get(Ctx, PromotedWidth);
assert(OrigTy->getPrimitiveSizeInBits().getFixedSize() <
ExtTy->getPrimitiveSizeInBits().getFixedSize() &&
@@ -145,7 +144,7 @@ class TypePromotion : public FunctionPass {
unsigned RegisterBitWidth = 0;
SmallPtrSet<Value*, 16> AllVisited;
SmallPtrSet<Instruction*, 8> SafeToPromote;
- SmallVector<Instruction*, 4> SafeWrap;
+ SmallPtrSet<Instruction *, 4> SafeWrap;
// Does V have the same size result type as TypeSize.
bool EqualTypeSize(Value *V);
@@ -183,6 +182,7 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<TargetTransformInfoWrapperPass>();
AU.addRequired<TargetPassConfig>();
+ AU.setPreservesCFG();
}
StringRef getPassName() const override { return PASS_NAME; }
@@ -192,11 +192,8 @@ public:
}
-static bool GenerateSignBits(Value *V) {
- if (!isa<Instruction>(V))
- return false;
-
- unsigned Opc = cast<Instruction>(V)->getOpcode();
+static bool GenerateSignBits(Instruction *I) {
+ unsigned Opc = I->getOpcode();
return Opc == Instruction::AShr || Opc == Instruction::SDiv ||
Opc == Instruction::SRem || Opc == Instruction::SExt;
}
@@ -283,7 +280,7 @@ bool TypePromotion::isSafeWrap(Instruction *I) {
// wrap in respect to itself in the original bitwidth. If it doesn't wrap,
// just underflows the range, the icmp would give the same result whether the
// result has been truncated or not. We calculate this by:
- // - Zero extending both constants, if needed, to 32-bits.
+ // - Zero extending both constants, if needed, to RegisterBitWidth.
// - Take the absolute value of I's constant, adding this to the icmp const.
// - Check that this value is not out of range for small type. If it is, it
// means that it has underflowed enough to wrap around the icmp constant.
@@ -335,53 +332,46 @@ bool TypePromotion::isSafeWrap(Instruction *I) {
if (Opc != Instruction::Add && Opc != Instruction::Sub)
return false;
- if (!I->hasOneUse() ||
- !isa<ICmpInst>(*I->user_begin()) ||
+ if (!I->hasOneUse() || !isa<ICmpInst>(*I->user_begin()) ||
!isa<ConstantInt>(I->getOperand(1)))
return false;
- ConstantInt *OverflowConst = cast<ConstantInt>(I->getOperand(1));
- bool NegImm = OverflowConst->isNegative();
- bool IsDecreasing = ((Opc == Instruction::Sub) && !NegImm) ||
- ((Opc == Instruction::Add) && NegImm);
- if (!IsDecreasing)
- return false;
-
// Don't support an icmp that deals with sign bits.
auto *CI = cast<ICmpInst>(*I->user_begin());
if (CI->isSigned() || CI->isEquality())
return false;
- ConstantInt *ICmpConst = nullptr;
+ ConstantInt *ICmpConstant = nullptr;
if (auto *Const = dyn_cast<ConstantInt>(CI->getOperand(0)))
- ICmpConst = Const;
+ ICmpConstant = Const;
else if (auto *Const = dyn_cast<ConstantInt>(CI->getOperand(1)))
- ICmpConst = Const;
+ ICmpConstant = Const;
else
return false;
- // Now check that the result can't wrap on itself.
- APInt Total = ICmpConst->getValue().getBitWidth() < 32 ?
- ICmpConst->getValue().zext(32) : ICmpConst->getValue();
-
- Total += OverflowConst->getValue().getBitWidth() < 32 ?
- OverflowConst->getValue().abs().zext(32) : OverflowConst->getValue().abs();
-
- APInt Max = APInt::getAllOnesValue(TypePromotion::TypeSize);
-
- if (Total.getBitWidth() > Max.getBitWidth()) {
- if (Total.ugt(Max.zext(Total.getBitWidth())))
- return false;
- } else if (Max.getBitWidth() > Total.getBitWidth()) {
- if (Total.zext(Max.getBitWidth()).ugt(Max))
- return false;
- } else if (Total.ugt(Max))
+ const APInt &ICmpConst = ICmpConstant->getValue();
+ APInt OverflowConst = cast<ConstantInt>(I->getOperand(1))->getValue();
+ if (Opc == Instruction::Sub)
+ OverflowConst = -OverflowConst;
+ if (!OverflowConst.isNonPositive())
return false;
- LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for "
- << *I << "\n");
- SafeWrap.push_back(I);
- return true;
+ // Using C1 = OverflowConst and C2 = ICmpConst, we can use either prove that:
+ // zext(x) + sext(C1) <u zext(C2) if C1 < 0 and C1 >s C2
+ // zext(x) + sext(C1) <u sext(C2) if C1 < 0 and C1 <=s C2
+ if (OverflowConst.sgt(ICmpConst)) {
+ LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for sext "
+ << "const of " << *I << "\n");
+ SafeWrap.insert(I);
+ return true;
+ } else {
+ LLVM_DEBUG(dbgs() << "IR Promotion: Allowing safe overflow for sext "
+ << "const of " << *I << " and " << *CI << "\n");
+ SafeWrap.insert(I);
+ SafeWrap.insert(CI);
+ return true;
+ }
+ return false;
}
bool TypePromotion::shouldPromote(Value *V) {
@@ -403,17 +393,14 @@ bool TypePromotion::shouldPromote(Value *V) {
/// Return whether we can safely mutate V's type to ExtTy without having to be
/// concerned with zero extending or truncation.
-static bool isPromotedResultSafe(Value *V) {
- if (GenerateSignBits(V))
+static bool isPromotedResultSafe(Instruction *I) {
+ if (GenerateSignBits(I))
return false;
- if (!isa<Instruction>(V))
+ if (!isa<OverflowingBinaryOperator>(I))
return true;
- if (!isa<OverflowingBinaryOperator>(V))
- return true;
-
- return cast<Instruction>(V)->hasNoUnsignedWrap();
+ return I->hasNoUnsignedWrap();
}
void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
@@ -422,7 +409,7 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
bool ReplacedAll = true;
LLVM_DEBUG(dbgs() << "IR Promotion: Replacing " << *From << " with " << *To
- << "\n");
+ << "\n");
for (Use &U : From->uses()) {
auto *User = cast<Instruction>(U.getUser());
@@ -441,39 +428,6 @@ void IRPromoter::ReplaceAllUsersOfWith(Value *From, Value *To) {
InstsToRemove.insert(I);
}
-void IRPromoter::PrepareWrappingAdds() {
- LLVM_DEBUG(dbgs() << "IR Promotion: Prepare wrapping adds.\n");
- IRBuilder<> Builder{Ctx};
-
- // For adds that safely wrap and use a negative immediate as operand 1, we
- // create an equivalent instruction using a positive immediate.
- // That positive immediate can then be zext along with all the other
- // immediates later.
- for (auto *I : SafeWrap) {
- if (I->getOpcode() != Instruction::Add)
- continue;
-
- LLVM_DEBUG(dbgs() << "IR Promotion: Adjusting " << *I << "\n");
- assert((isa<ConstantInt>(I->getOperand(1)) &&
- cast<ConstantInt>(I->getOperand(1))->isNegative()) &&
- "Wrapping should have a negative immediate as the second operand");
-
- auto Const = cast<ConstantInt>(I->getOperand(1));
- auto *NewConst = ConstantInt::get(Ctx, Const->getValue().abs());
- Builder.SetInsertPoint(I);
- Value *NewVal = Builder.CreateSub(I->getOperand(0), NewConst);
- if (auto *NewInst = dyn_cast<Instruction>(NewVal)) {
- NewInst->copyIRFlags(I);
- NewInsts.insert(NewInst);
- }
- InstsToRemove.insert(I);
- I->replaceAllUsesWith(NewVal);
- LLVM_DEBUG(dbgs() << "IR Promotion: New equivalent: " << *NewVal << "\n");
- }
- for (auto *I : NewInsts)
- Visited.insert(I);
-}
-
void IRPromoter::ExtendSources() {
IRBuilder<> Builder{Ctx};
@@ -515,8 +469,6 @@ void IRPromoter::ExtendSources() {
void IRPromoter::PromoteTree() {
LLVM_DEBUG(dbgs() << "IR Promotion: Mutating the tree..\n");
- IRBuilder<> Builder{Ctx};
-
// Mutate the types of the instructions within the tree. Here we handle
// constant operands.
for (auto *V : Visited) {
@@ -533,14 +485,16 @@ void IRPromoter::PromoteTree() {
continue;
if (auto *Const = dyn_cast<ConstantInt>(Op)) {
- Constant *NewConst = ConstantExpr::getZExt(Const, ExtTy);
+ Constant *NewConst = SafeWrap.contains(I)
+ ? ConstantExpr::getSExt(Const, ExtTy)
+ : ConstantExpr::getZExt(Const, ExtTy);
I->setOperand(i, NewConst);
} else if (isa<UndefValue>(Op))
I->setOperand(i, UndefValue::get(ExtTy));
}
- // Mutate the result type, unless this is an icmp.
- if (!isa<ICmpInst>(I)) {
+ // Mutate the result type, unless this is an icmp or switch.
+ if (!isa<ICmpInst>(I) && !isa<SwitchInst>(I)) {
I->mutateType(ExtTy);
Promoted.insert(I);
}
@@ -575,7 +529,7 @@ void IRPromoter::TruncateSinks() {
// Handle calls separately as we need to iterate over arg operands.
if (auto *Call = dyn_cast<CallInst>(I)) {
- for (unsigned i = 0; i < Call->getNumArgOperands(); ++i) {
+ for (unsigned i = 0; i < Call->arg_size(); ++i) {
Value *Arg = Call->getArgOperand(i);
Type *Ty = TruncTysMap[Call][i];
if (Instruction *Trunc = InsertTrunc(Arg, Ty)) {
@@ -678,10 +632,8 @@ void IRPromoter::Mutate() {
// Cache original types of the values that will likely need truncating
for (auto *I : Sinks) {
if (auto *Call = dyn_cast<CallInst>(I)) {
- for (unsigned i = 0; i < Call->getNumArgOperands(); ++i) {
- Value *Arg = Call->getArgOperand(i);
+ for (Value *Arg : Call->args())
TruncTysMap[Call].push_back(Arg->getType());
- }
} else if (auto *Switch = dyn_cast<SwitchInst>(I))
TruncTysMap[I].push_back(Switch->getCondition()->getType());
else {
@@ -696,10 +648,6 @@ void IRPromoter::Mutate() {
TruncTysMap[Trunc].push_back(Trunc->getDestTy());
}
- // Convert adds using negative immediates to equivalent instructions that use
- // positive constants.
- PrepareWrappingAdds();
-
// Insert zext instructions between sources and their users.
ExtendSources();
@@ -798,7 +746,7 @@ bool TypePromotion::isLegalToPromote(Value *V) {
if (SafeToPromote.count(I))
return true;
- if (isPromotedResultSafe(V) || isSafeWrap(I)) {
+ if (isPromotedResultSafe(I) || isSafeWrap(I)) {
SafeToPromote.insert(I);
return true;
}
@@ -815,7 +763,7 @@ bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth) {
return false;
LLVM_DEBUG(dbgs() << "IR Promotion: TryToPromote: " << *V << ", from "
- << TypeSize << " bits to " << PromotedWidth << "\n");
+ << TypeSize << " bits to " << PromotedWidth << "\n");
SetVector<Value*> WorkList;
SetVector<Value*> Sources;