forked from OSchip/llvm-project
[ValueTracking] Handle shl pair in isKnownNonEqual()
Handle (x << s) != (y << s) where x != y and the shifts are non-wrapping. Once again, this establishes parity with the corresponing mul fold that already exists. The shift case is more powerful because we don't need to guard against multiplies by zero.
This commit is contained in:
parent
9666e89d57
commit
fd7df0cf38
|
@ -2655,6 +2655,20 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
|
||||||
Depth + 1, Q);
|
Depth + 1, Q);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Instruction::Shl: {
|
||||||
|
// Same as multiplies, with the difference that we don't need to check
|
||||||
|
// for a non-zero multiply. Shifts always multiply by non-zero.
|
||||||
|
auto *OBO1 = cast<OverflowingBinaryOperator>(O1);
|
||||||
|
auto *OBO2 = cast<OverflowingBinaryOperator>(O2);
|
||||||
|
if ((!OBO1->hasNoUnsignedWrap() || !OBO2->hasNoUnsignedWrap()) &&
|
||||||
|
(!OBO1->hasNoSignedWrap() || !OBO2->hasNoSignedWrap()))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (O1->getOperand(1) == O2->getOperand(1))
|
||||||
|
return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0),
|
||||||
|
Depth + 1, Q);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Instruction::SExt:
|
case Instruction::SExt:
|
||||||
case Instruction::ZExt:
|
case Instruction::ZExt:
|
||||||
if (O1->getOperand(0)->getType() == O2->getOperand(0)->getType())
|
if (O1->getOperand(0)->getType() == O2->getOperand(0)->getType())
|
||||||
|
|
|
@ -406,13 +406,7 @@ define i1 @shl_op_may_be_zero(i16 %x) {
|
||||||
|
|
||||||
define i1 @shl_shl_nuw(i8 %B, i8 %shift) {
|
define i1 @shl_shl_nuw(i8 %B, i8 %shift) {
|
||||||
; CHECK-LABEL: @shl_shl_nuw(
|
; CHECK-LABEL: @shl_shl_nuw(
|
||||||
; CHECK-NEXT: [[A:%.*]] = add i8 [[B:%.*]], 1
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: [[A_OP:%.*]] = shl nuw i8 [[A]], [[SHIFT:%.*]]
|
|
||||||
; CHECK-NEXT: [[B_OP:%.*]] = shl nuw i8 [[B]], [[SHIFT]]
|
|
||||||
; CHECK-NEXT: [[A_OP2:%.*]] = mul nuw i8 [[A_OP]], 3
|
|
||||||
; CHECK-NEXT: [[B_OP2:%.*]] = mul nuw i8 [[B_OP]], 3
|
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A_OP2]], [[B_OP2]]
|
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
%A = add i8 %B, 1
|
%A = add i8 %B, 1
|
||||||
%A.op = shl nuw i8 %A, %shift
|
%A.op = shl nuw i8 %A, %shift
|
||||||
|
@ -425,13 +419,7 @@ define i1 @shl_shl_nuw(i8 %B, i8 %shift) {
|
||||||
|
|
||||||
define i1 @shl_shl_nsw(i8 %B, i8 %shift) {
|
define i1 @shl_shl_nsw(i8 %B, i8 %shift) {
|
||||||
; CHECK-LABEL: @shl_shl_nsw(
|
; CHECK-LABEL: @shl_shl_nsw(
|
||||||
; CHECK-NEXT: [[A:%.*]] = add i8 [[B:%.*]], 1
|
; CHECK-NEXT: ret i1 false
|
||||||
; CHECK-NEXT: [[A_OP:%.*]] = shl nsw i8 [[A]], [[SHIFT:%.*]]
|
|
||||||
; CHECK-NEXT: [[B_OP:%.*]] = shl nsw i8 [[B]], [[SHIFT]]
|
|
||||||
; CHECK-NEXT: [[A_OP2:%.*]] = mul nuw i8 [[A_OP]], 3
|
|
||||||
; CHECK-NEXT: [[B_OP2:%.*]] = mul nuw i8 [[B_OP]], 3
|
|
||||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A_OP2]], [[B_OP2]]
|
|
||||||
; CHECK-NEXT: ret i1 [[CMP]]
|
|
||||||
;
|
;
|
||||||
%A = add i8 %B, 1
|
%A = add i8 %B, 1
|
||||||
%A.op = shl nsw i8 %A, %shift
|
%A.op = shl nsw i8 %A, %shift
|
||||||
|
|
Loading…
Reference in New Issue