bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS);
bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS);
bool WillNotOverflowSignedSub(Value *LHS, Value *RHS);
+ bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS);
Value *EmitGEPOffset(User *GEP);
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
return false;
}
+/// \brief Return true if we can prove that:
+/// (sub LHS, RHS) === (sub nuw LHS, RHS)
+bool InstCombiner::WillNotOverflowUnsignedSub(Value *LHS, Value *RHS) {
+ // If the LHS is negative and the RHS is non-negative, no unsigned wrap.
+ bool LHSKnownNonNegative, LHSKnownNegative;
+ bool RHSKnownNonNegative, RHSKnownNegative;
+ ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, DL, 0);
+ ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, DL, 0);
+ if (LHSKnownNegative && RHSKnownNonNegative)
+ return true;
+
+ return false;
+}
+
// Checks if any operand is negative and we can convert add to sub.
// This function checks for following negative patterns
// ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
Changed = true;
I.setHasNoSignedWrap(true);
}
+ if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedSub(Op0, Op1)) {
+ Changed = true;
+ I.setHasNoUnsignedWrap(true);
+ }
return Changed ? &I : nullptr;
}
; CHECK-LABEL: @test42(
; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7
; CHECK-NEXT: [[AND1:%.*]] = and i4 %x, 7
-; CHECK-NEXT: [[RET:%.*]] = sub nsw i4 %a, %b
+; CHECK-NEXT: [[RET:%.*]] = sub nsw i4 [[AND]], [[AND1]]
+; CHECK: ret i4 [[RET]]
+}
+
+define i4 @test43(i4 %x, i4 %y) {
+ %a = or i4 %x, -8
+ %b = and i4 %y, 7
+ %c = sub i4 %a, %b
+ ret i4 %c
+; CHECK-LABEL: @test43(
+; CHECK-NEXT: [[OR:%.*]] = or i4 %x, -8
+; CHECK-NEXT: [[AND:%.*]] = and i4 %y, 7
+; CHECK-NEXT: [[RET:%.*]] = sub nuw i4 [[OR]], [[AND]]
; CHECK: ret i4 [[RET]]
}