diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 65 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 85 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/GVN.cpp | 39 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/NewGVN.cpp | 40 |
4 files changed, 68 insertions, 161 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 7e26dee3452..963542c50d8 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2667,53 +2667,28 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { return ExtractValueInst::Create(IV->getInsertedValueOperand(), makeArrayRef(exti, exte)); } - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Agg)) { - // We're extracting from an intrinsic, see if we're the only user, which - // allows us to simplify multiple result intrinsics to simpler things that - // just get one value. - if (II->hasOneUse()) { - // Check if we're grabbing the overflow bit or the result of a 'with - // overflow' intrinsic. If it's the latter we can remove the intrinsic + if (WithOverflowInst *WO = dyn_cast<WithOverflowInst>(Agg)) { + // We're extracting from an overflow intrinsic, see if we're the only user, + // which allows us to simplify multiple result intrinsics to simpler + // things that just get one value. + if (WO->hasOneUse()) { + // Check if we're grabbing only the result of a 'with overflow' intrinsic // and replace it with a traditional binary instruction. - switch (II->getIntrinsicID()) { - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - if (*EV.idx_begin() == 0) { // Normal result. - Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); - replaceInstUsesWith(*II, UndefValue::get(II->getType())); - eraseInstFromFunction(*II); - return BinaryOperator::CreateAdd(LHS, RHS); - } - - // If the normal result of the add is dead, and the RHS is a constant, - // we can transform this into a range comparison. - // overflow = uadd a, -4 --> overflow = icmp ugt a, 3 - if (II->getIntrinsicID() == Intrinsic::uadd_with_overflow) - if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getArgOperand(1))) - return new ICmpInst(ICmpInst::ICMP_UGT, II->getArgOperand(0), - ConstantExpr::getNot(CI)); - break; - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - if (*EV.idx_begin() == 0) { // Normal result. - Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); - replaceInstUsesWith(*II, UndefValue::get(II->getType())); - eraseInstFromFunction(*II); - return BinaryOperator::CreateSub(LHS, RHS); - } - break; - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - if (*EV.idx_begin() == 0) { // Normal result. - Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); - replaceInstUsesWith(*II, UndefValue::get(II->getType())); - eraseInstFromFunction(*II); - return BinaryOperator::CreateMul(LHS, RHS); - } - break; - default: - break; + if (*EV.idx_begin() == 0) { + Instruction::BinaryOps BinOp = WO->getBinaryOp(); + Value *LHS = WO->getLHS(), *RHS = WO->getRHS(); + replaceInstUsesWith(*WO, UndefValue::get(WO->getType())); + eraseInstFromFunction(*WO); + return BinaryOperator::Create(BinOp, LHS, RHS); } + + // If the normal result of the add is dead, and the RHS is a constant, + // we can transform this into a range comparison. + // overflow = uadd a, -4 --> overflow = icmp ugt a, 3 + if (WO->getIntrinsicID() == Intrinsic::uadd_with_overflow) + if (ConstantInt *CI = dyn_cast<ConstantInt>(WO->getRHS())) + return new ICmpInst(ICmpInst::ICMP_UGT, WO->getLHS(), + ConstantExpr::getNot(CI)); } } if (LoadInst *L = dyn_cast<LoadInst>(Agg)) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index e9af934fbb6..bc4daf1c9c1 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -399,59 +399,38 @@ static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI, } // See if we can prove that the given overflow intrinsic will not overflow. -static bool willNotOverflow(IntrinsicInst *II, LazyValueInfo *LVI) { - using OBO = OverflowingBinaryOperator; - auto NoWrap = [&] (Instruction::BinaryOps BinOp, unsigned NoWrapKind) { - Value *RHS = II->getOperand(1); - ConstantRange RRange = LVI->getConstantRange(RHS, II->getParent(), II); - ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion( - BinOp, RRange, NoWrapKind); - // As an optimization, do not compute LRange if we do not need it. - if (NWRegion.isEmptySet()) - return false; - Value *LHS = II->getOperand(0); - ConstantRange LRange = LVI->getConstantRange(LHS, II->getParent(), II); - return NWRegion.contains(LRange); - }; - switch (II->getIntrinsicID()) { - default: - break; - case Intrinsic::uadd_with_overflow: - return NoWrap(Instruction::Add, OBO::NoUnsignedWrap); - case Intrinsic::sadd_with_overflow: - return NoWrap(Instruction::Add, OBO::NoSignedWrap); - case Intrinsic::usub_with_overflow: - return NoWrap(Instruction::Sub, OBO::NoUnsignedWrap); - case Intrinsic::ssub_with_overflow: - return NoWrap(Instruction::Sub, OBO::NoSignedWrap); - } - return false; +static bool willNotOverflow(WithOverflowInst *WO, LazyValueInfo *LVI) { + // TODO: Also support multiplication. + Instruction::BinaryOps BinOp = WO->getBinaryOp(); + if (BinOp == Instruction::Mul) + return false; + + Value *RHS = WO->getRHS(); + ConstantRange RRange = LVI->getConstantRange(RHS, WO->getParent(), WO); + ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + BinOp, RRange, WO->getNoWrapKind()); + // As an optimization, do not compute LRange if we do not need it. + if (NWRegion.isEmptySet()) + return false; + Value *LHS = WO->getLHS(); + ConstantRange LRange = LVI->getConstantRange(LHS, WO->getParent(), WO); + return NWRegion.contains(LRange); } -static void processOverflowIntrinsic(IntrinsicInst *II) { - IRBuilder<> B(II); - Value *NewOp = nullptr; - switch (II->getIntrinsicID()) { - default: - llvm_unreachable("Unexpected instruction."); - case Intrinsic::uadd_with_overflow: - NewOp = B.CreateNUWAdd(II->getOperand(0), II->getOperand(1), II->getName()); - break; - case Intrinsic::sadd_with_overflow: - NewOp = B.CreateNSWAdd(II->getOperand(0), II->getOperand(1), II->getName()); - break; - case Intrinsic::usub_with_overflow: - NewOp = B.CreateNUWSub(II->getOperand(0), II->getOperand(1), II->getName()); - break; - case Intrinsic::ssub_with_overflow: - NewOp = B.CreateNSWSub(II->getOperand(0), II->getOperand(1), II->getName()); - break; - } +static void processOverflowIntrinsic(WithOverflowInst *WO) { + IRBuilder<> B(WO); + Value *NewOp = B.CreateBinOp( + WO->getBinaryOp(), WO->getLHS(), WO->getRHS(), WO->getName()); + if (WO->isSigned()) + cast<Instruction>(NewOp)->setHasNoSignedWrap(); + else + cast<Instruction>(NewOp)->setHasNoUnsignedWrap(); + + Value *NewI = B.CreateInsertValue(UndefValue::get(WO->getType()), NewOp, 0); + NewI = B.CreateInsertValue(NewI, ConstantInt::getFalse(WO->getContext()), 1); + WO->replaceAllUsesWith(NewI); + WO->eraseFromParent(); ++NumOverflows; - Value *NewI = B.CreateInsertValue(UndefValue::get(II->getType()), NewOp, 0); - NewI = B.CreateInsertValue(NewI, ConstantInt::getFalse(II->getContext()), 1); - II->replaceAllUsesWith(NewI); - II->eraseFromParent(); } /// Infer nonnull attributes for the arguments at the specified callsite. @@ -459,9 +438,9 @@ static bool processCallSite(CallSite CS, LazyValueInfo *LVI) { SmallVector<unsigned, 4> ArgNos; unsigned ArgNo = 0; - if (auto *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { - if (willNotOverflow(II, LVI)) { - processOverflowIntrinsic(II); + if (auto *WO = dyn_cast<WithOverflowInst>(CS.getInstruction())) { + if (willNotOverflow(WO, LVI)) { + processOverflowIntrinsic(WO); return true; } } diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index a02f32f5643..985941eb3c4 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -329,36 +329,15 @@ GVN::Expression GVN::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) { e.type = EI->getType(); e.opcode = 0; - IntrinsicInst *I = dyn_cast<IntrinsicInst>(EI->getAggregateOperand()); - if (I != nullptr && EI->getNumIndices() == 1 && *EI->idx_begin() == 0 ) { - // EI might be an extract from one of our recognised intrinsics. If it - // is we'll synthesize a semantically equivalent expression instead on - // an extract value expression. - switch (I->getIntrinsicID()) { - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: - e.opcode = Instruction::Add; - break; - case Intrinsic::ssub_with_overflow: - case Intrinsic::usub_with_overflow: - e.opcode = Instruction::Sub; - break; - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - e.opcode = Instruction::Mul; - break; - default: - break; - } - - if (e.opcode != 0) { - // Intrinsic recognized. Grab its args to finish building the expression. - assert(I->getNumArgOperands() == 2 && - "Expect two args for recognised intrinsics."); - e.varargs.push_back(lookupOrAdd(I->getArgOperand(0))); - e.varargs.push_back(lookupOrAdd(I->getArgOperand(1))); - return e; - } + WithOverflowInst *WO = dyn_cast<WithOverflowInst>(EI->getAggregateOperand()); + if (WO != nullptr && EI->getNumIndices() == 1 && *EI->idx_begin() == 0) { + // EI is an extract from one of our with.overflow intrinsics. Synthesize + // a semantically equivalent expression instead of an extract value + // expression. + e.opcode = WO->getBinaryOp(); + e.varargs.push_back(lookupOrAdd(WO->getLHS())); + e.varargs.push_back(lookupOrAdd(WO->getRHS())); + return e; } // Not a recognised intrinsic. Fall back to producing an extract value diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 0474caf7c47..c54da4f72df 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1814,39 +1814,13 @@ NewGVN::performSymbolicPHIEvaluation(ArrayRef<ValPair> PHIOps, const Expression * NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) const { if (auto *EI = dyn_cast<ExtractValueInst>(I)) { - auto *II = dyn_cast<IntrinsicInst>(EI->getAggregateOperand()); - if (II && EI->getNumIndices() == 1 && *EI->idx_begin() == 0) { - unsigned Opcode = 0; - // EI might be an extract from one of our recognised intrinsics. If it - // is we'll synthesize a semantically equivalent expression instead on - // an extract value expression. - switch (II->getIntrinsicID()) { - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: - Opcode = Instruction::Add; - break; - case Intrinsic::ssub_with_overflow: - case Intrinsic::usub_with_overflow: - Opcode = Instruction::Sub; - break; - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - Opcode = Instruction::Mul; - break; - default: - break; - } - - if (Opcode != 0) { - // Intrinsic recognized. Grab its args to finish building the - // expression. - assert(II->getNumArgOperands() == 2 && - "Expect two args for recognised intrinsics."); - return createBinaryExpression(Opcode, EI->getType(), - II->getArgOperand(0), - II->getArgOperand(1), I); - } - } + auto *WO = dyn_cast<WithOverflowInst>(EI->getAggregateOperand()); + if (WO && EI->getNumIndices() == 1 && *EI->idx_begin() == 0) + // EI is an extract from one of our with.overflow intrinsics. Synthesize + // a semantically equivalent expression instead of an extract value + // expression. + return createBinaryExpression(WO->getBinaryOp(), EI->getType(), + WO->getLHS(), WO->getRHS(), I); } return createAggregateValueExpression(I); |

