This is a retry of rL300977 which was reverted because of infinite loops.
We have fixed all of the known places where that would happen, but there's
still a chance that this patch will cause infinite loops.
This matches the demanded bits behavior in the DAG and should fix:
https://bugs.llvm.org/show_bug.cgi?id=32706
Differential Revision: https://reviews.llvm.org/D32255
return InsertNewInstWith(And, *I);
}
- // If the RHS is a constant, see if we can simplify it.
- // FIXME: for XOR, we prefer to force bits to 1 if they will make a -1.
- if (ShrinkDemandedConstant(I, 1, DemandedMask))
- return I;
+ // If the RHS is a constant, see if we can change it. Don't alter a -1
+ // constant because that's a canonical 'not' op, and that is better for
+ // combining, SCEV, and codegen.
+ const APInt *C;
+ if (match(I->getOperand(1), m_APInt(C)) && !C->isAllOnesValue()) {
+ if ((*C | ~DemandedMask).isAllOnesValue()) {
+ // Force bits to 1 to create a 'not' op.
+ I->setOperand(1, ConstantInt::getAllOnesValue(VTy));
+ return I;
+ }
+ // If we can't turn this into a 'not', try to shrink the constant.
+ if (ShrinkDemandedConstant(I, 1, DemandedMask))
+ return I;
+ }
// If our LHS is an 'and' and if it has one use, and if any of the bits we
// are flipping are known to be set, then the xor is just resetting those
define <4 x i32> @and_xor_common_op_constant(<4 x i32> %A) {
; CHECK-LABEL: @and_xor_common_op_constant(
-; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i32> [[A:%.*]], <i32 7, i32 7, i32 7, i32 7>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i32> [[A:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i32> [[TMP1]], <i32 1, i32 2, i32 3, i32 4>
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
;
define i32 @and_xor_not_common_op(i32 %a, i32 %b) {
; CHECK-LABEL: @and_xor_not_common_op(
-; CHECK-NEXT: [[T4:%.*]] = and i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[T4:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: ret i32 [[T4]]
;
%b2 = xor i32 %b, -1
define i8 @not_or(i8 %x) {
; CHECK-LABEL: @not_or(
-; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], 7
-; CHECK-NEXT: [[OR:%.*]] = xor i8 [[TMP1]], -8
+; CHECK-NEXT: [[NOTX:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[NOTX]], 7
; CHECK-NEXT: ret i8 [[OR]]
;
%notx = xor i8 %x, -1
define i8 @not_or_xor(i8 %x) {
; CHECK-LABEL: @not_or_xor(
-; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], 7
-; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[TMP1]], -12
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -8
+; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[TMP1]], -13
; CHECK-NEXT: ret i8 [[XOR]]
;
%notx = xor i8 %x, -1
define i8 @xor_or_not_uses(i8 %x, i8* %p) {
; CHECK-LABEL: @xor_or_not_uses(
-; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X:%.*]], 7
-; CHECK-NEXT: [[OR:%.*]] = xor i8 [[TMP1]], -8
+; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[NX]], 7
; CHECK-NEXT: store i8 [[OR]], i8* [[P:%.*]], align 1
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], -12
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[OR]], 12
; CHECK-NEXT: ret i8 [[R]]
;
%nx = xor i8 %x, -1
define i32 @not_is_canonical(i32 %x, i32 %y) {
; CHECK-LABEL: @not_is_canonical(
-; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[X:%.*]], 1073741823
+; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[X:%.*]], -1
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], [[Y:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[ADD]], 2
; CHECK-NEXT: ret i32 [[MUL]]