}
case Instruction::PHI: {
const PHINode *P = cast<PHINode>(I);
- // Handle the case of a simple two-predecessor recurrence PHI.
- // There's a lot more that could theoretically be done here, but
- // this is sufficient to catch some interesting cases.
- if (P->getNumIncomingValues() == 2) {
- for (unsigned i = 0; i != 2; ++i) {
- Value *L = P->getIncomingValue(i);
- Value *R = P->getIncomingValue(!i);
- Instruction *RInst = P->getIncomingBlock(!i)->getTerminator();
- Instruction *LInst = P->getIncomingBlock(i)->getTerminator();
- Operator *LU = dyn_cast<Operator>(L);
- if (!LU)
- continue;
- unsigned Opcode = LU->getOpcode();
-
-
- // If this is a shift recurrence, we know the bits being shifted in.
- // We can combine that with information about the start value of the
- // recurrence to conclude facts about the result.
- if (Opcode == Instruction::LShr ||
- Opcode == Instruction::AShr ||
- Opcode == Instruction::Shl) {
- Value *LL = LU->getOperand(0);
- Value *LR = LU->getOperand(1);
- // Find a recurrence.
- if (LL == I)
- L = LR;
- else
- continue; // Check for recurrence with L and R flipped.
-
- // We have matched a recurrence of the form:
- // %iv = [R, %entry], [%iv.next, %backedge]
- // %iv.next = shift_op %iv, L
-
- // Recurse with the phi context to avoid concern about whether facts
- // inferred hold at original context instruction. TODO: It may be
- // correct to use the original context. IF warranted, explore and
- // add sufficient tests to cover.
- Query RecQ = Q;
- RecQ.CxtI = P;
- computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
- switch (Opcode) {
- case Instruction::Shl:
- // A shl recurrence will only increase the tailing zeros
- Known.Zero.setLowBits(Known2.countMinTrailingZeros());
- break;
- case Instruction::LShr:
- // A lshr recurrence will preserve the leading zeros of the
- // start value
- Known.Zero.setHighBits(Known2.countMinLeadingZeros());
- break;
- case Instruction::AShr:
- // An ashr recurrence will extend the initial sign bit
- Known.Zero.setHighBits(Known2.countMinLeadingZeros());
- Known.One.setHighBits(Known2.countMinLeadingOnes());
- break;
- };
- }
+ BinaryOperator *BO = nullptr;
+ Value *R = nullptr, *L = nullptr;
+ if (matchSimpleRecurrence(P, BO, R, L)) {
+ // Handle the case of a simple two-predecessor recurrence PHI.
+ // There's a lot more that could theoretically be done here, but
+ // this is sufficient to catch some interesting cases.
+ unsigned Opcode = BO->getOpcode();
+
+ // If this is a shift recurrence, we know the bits being shifted in.
+ // We can combine that with information about the start value of the
+ // recurrence to conclude facts about the result.
+ if (Opcode == Instruction::LShr ||
+ Opcode == Instruction::AShr ||
+ Opcode == Instruction::Shl) {
+
+ // We have matched a recurrence of the form:
+ // %iv = [R, %entry], [%iv.next, %backedge]
+ // %iv.next = shift_op %iv, L
+
+ // Recurse with the phi context to avoid concern about whether facts
+ // inferred hold at original context instruction. TODO: It may be
+ // correct to use the original context. IF warranted, explore and
+ // add sufficient tests to cover.
+ Query RecQ = Q;
+ RecQ.CxtI = P;
+ computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
+ switch (Opcode) {
+ case Instruction::Shl:
+ // A shl recurrence will only increase the tailing zeros
+ Known.Zero.setLowBits(Known2.countMinTrailingZeros());
+ break;
+ case Instruction::LShr:
+ // A lshr recurrence will preserve the leading zeros of the
+ // start value
+ Known.Zero.setHighBits(Known2.countMinLeadingZeros());
+ break;
+ case Instruction::AShr:
+ // An ashr recurrence will extend the initial sign bit
+ Known.Zero.setHighBits(Known2.countMinLeadingZeros());
+ Known.One.setHighBits(Known2.countMinLeadingOnes());
+ break;
+ };
+ }
- // Check for operations that have the property that if
- // both their operands have low zero bits, the result
- // will have low zero bits.
- if (Opcode == Instruction::Add ||
- Opcode == Instruction::Sub ||
- Opcode == Instruction::And ||
- Opcode == Instruction::Or ||
- Opcode == Instruction::Mul) {
- Value *LL = LU->getOperand(0);
- Value *LR = LU->getOperand(1);
- // Find a recurrence.
- if (LL == I)
- L = LR;
- else if (LR == I)
- L = LL;
- else
- continue; // Check for recurrence with L and R flipped.
-
- // Change the context instruction to the "edge" that flows into the
- // phi. This is important because that is where the value is actually
- // "evaluated" even though it is used later somewhere else. (see also
- // D69571).
- Query RecQ = Q;
-
- // Ok, we have a PHI of the form L op= R. Check for low
- // zero bits.
- RecQ.CxtI = RInst;
- computeKnownBits(R, Known2, Depth + 1, RecQ);
-
- // We need to take the minimum number of known bits
- KnownBits Known3(BitWidth);
- RecQ.CxtI = LInst;
- computeKnownBits(L, Known3, Depth + 1, RecQ);
-
- Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
- Known3.countMinTrailingZeros()));
-
- auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(LU);
- if (OverflowOp && Q.IIQ.hasNoSignedWrap(OverflowOp)) {
- // If initial value of recurrence is nonnegative, and we are adding
- // a nonnegative number with nsw, the result can only be nonnegative
- // or poison value regardless of the number of times we execute the
- // add in phi recurrence. If initial value is negative and we are
- // adding a negative number with nsw, the result can only be
- // negative or poison value. Similar arguments apply to sub and mul.
- //
- // (add non-negative, non-negative) --> non-negative
- // (add negative, negative) --> negative
- if (Opcode == Instruction::Add) {
- if (Known2.isNonNegative() && Known3.isNonNegative())
- Known.makeNonNegative();
- else if (Known2.isNegative() && Known3.isNegative())
- Known.makeNegative();
- }
-
- // (sub nsw non-negative, negative) --> non-negative
- // (sub nsw negative, non-negative) --> negative
- else if (Opcode == Instruction::Sub && LL == I) {
- if (Known2.isNonNegative() && Known3.isNegative())
- Known.makeNonNegative();
- else if (Known2.isNegative() && Known3.isNonNegative())
- Known.makeNegative();
- }
-
- // (mul nsw non-negative, non-negative) --> non-negative
- else if (Opcode == Instruction::Mul && Known2.isNonNegative() &&
- Known3.isNonNegative())
+ // Check for operations that have the property that if
+ // both their operands have low zero bits, the result
+ // will have low zero bits.
+ if (Opcode == Instruction::Add ||
+ Opcode == Instruction::Sub ||
+ Opcode == Instruction::And ||
+ Opcode == Instruction::Or ||
+ Opcode == Instruction::Mul) {
+ // Change the context instruction to the "edge" that flows into the
+ // phi. This is important because that is where the value is actually
+ // "evaluated" even though it is used later somewhere else. (see also
+ // D69571).
+ Query RecQ = Q;
+
+ unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
+ Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
+ Instruction *LInst = P->getIncomingBlock(1-OpNum)->getTerminator();
+
+ // Ok, we have a PHI of the form L op= R. Check for low
+ // zero bits.
+ RecQ.CxtI = RInst;
+ computeKnownBits(R, Known2, Depth + 1, RecQ);
+
+ // We need to take the minimum number of known bits
+ KnownBits Known3(BitWidth);
+ RecQ.CxtI = LInst;
+ computeKnownBits(L, Known3, Depth + 1, RecQ);
+
+ Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
+ Known3.countMinTrailingZeros()));
+
+ auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(BO);
+ if (OverflowOp && Q.IIQ.hasNoSignedWrap(OverflowOp)) {
+ // If initial value of recurrence is nonnegative, and we are adding
+ // a nonnegative number with nsw, the result can only be nonnegative
+ // or poison value regardless of the number of times we execute the
+ // add in phi recurrence. If initial value is negative and we are
+ // adding a negative number with nsw, the result can only be
+ // negative or poison value. Similar arguments apply to sub and mul.
+ //
+ // (add non-negative, non-negative) --> non-negative
+ // (add negative, negative) --> negative
+ if (Opcode == Instruction::Add) {
+ if (Known2.isNonNegative() && Known3.isNonNegative())
Known.makeNonNegative();
+ else if (Known2.isNegative() && Known3.isNegative())
+ Known.makeNegative();
}
- break;
+ // (sub nsw non-negative, negative) --> non-negative
+ // (sub nsw negative, non-negative) --> negative
+ else if (Opcode == Instruction::Sub && BO->getOperand(0) == I) {
+ if (Known2.isNonNegative() && Known3.isNegative())
+ Known.makeNonNegative();
+ else if (Known2.isNegative() && Known3.isNonNegative())
+ Known.makeNegative();
+ }
+
+ // (mul nsw non-negative, non-negative) --> non-negative
+ else if (Opcode == Instruction::Mul && Known2.isNonNegative() &&
+ Known3.isNonNegative())
+ Known.makeNonNegative();
}
+
+ break;
}
}
return {Intrinsic::not_intrinsic, false};
}
-bool llvm::matchSimpleRecurrence(PHINode *P, BinaryOperator *&BO,
+bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
Value *&Start, Value *&Step) {
// Handle the case of a simple two-predecessor recurrence PHI.
// There's a lot more that could theoretically be done here, but