[TargetLowering] try to create -1 constant operand for math ops via demanded bits

This reverses instcombine's demanded bits' transform which always tries to clear bits in constants.

As noted in PR35792 and shown in the test diffs:
https://bugs.llvm.org/show_bug.cgi?id=35792
...we can do better in codegen by trying to form -1. The x86 sub test shows a missed opportunity. 

I did investigate changing instcombine's behavior, but it would be more work to change 
canonicalization in IR. Clearing bits / shrinking constants can allow killing instructions, 
so we'd have to figure out how to not regress those cases.

Differential Revision: https://reviews.llvm.org/D42986


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324839 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjay Patel
2018-02-11 14:38:23 +00:00
parent 6c93e2af21
commit 3f985a3da1
4 changed files with 25 additions and 7 deletions
@@ -1232,6 +1232,27 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
}
return true;
}
// If we have a constant operand, we may be able to turn it into -1 if we
// do not demand the high bits. This can make the constant smaller to
// encode, allow more general folding, or match specialized instruction
// patterns (eg, 'blsr' on x86). Don't bother changing 1 to -1 because that
// is probably not useful (and could be detrimental).
ConstantSDNode *C = isConstOrConstSplat(Op1);
APInt HighMask = APInt::getHighBitsSet(NewMask.getBitWidth(), NewMaskLZ);
if (C && !C->isAllOnesValue() && !C->isOne() &&
(C->getAPIntValue() | HighMask).isAllOnesValue()) {
SDValue Neg1 = TLO.DAG.getAllOnesConstant(dl, VT);
// We can't guarantee that the new math op doesn't wrap, so explicitly
// clear those flags to prevent folding with a potential existing node
// that has those flags set.
SDNodeFlags Flags;
Flags.setNoSignedWrap(false);
Flags.setNoUnsignedWrap(false);
SDValue NewOp = TLO.DAG.getNode(Op.getOpcode(), dl, VT, Op0, Neg1, Flags);
return TLO.CombineTo(Op, NewOp);
}
LLVM_FALLTHROUGH;
}
default:
+1 -2
View File
@@ -4,8 +4,7 @@
define i64 @sub1_disguised_constant(i64 %x) {
; CHECK-LABEL: sub1_disguised_constant:
; CHECK: // %bb.0:
; CHECK-NEXT: orr w8, wzr, #0xffff
; CHECK-NEXT: add w8, w0, w8
; CHECK-NEXT: sub w8, w0, #1 // =1
; CHECK-NEXT: and w8, w0, w8
; CHECK-NEXT: and x0, x8, #0xffff
; CHECK-NEXT: ret
+1 -2
View File
@@ -813,8 +813,7 @@ define i64 @blsr64(i64 %x) {
define i64 @blsr_disguised_constant(i64 %x) {
; CHECK-LABEL: blsr_disguised_constant:
; CHECK: # %bb.0:
; CHECK-NEXT: leal 65535(%rdi), %eax
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: blsrl %edi, %eax
; CHECK-NEXT: movzwl %ax, %eax
; CHECK-NEXT: retq
%a1 = and i64 %x, 65535
+2 -3
View File
@@ -101,7 +101,7 @@ define i32 @test8(i32 %x) {
define i64 @add_neg_one(i64 %x) {
; CHECK-LABEL: add_neg_one:
; CHECK: # %bb.0:
; CHECK-NEXT: leal 65535(%rdi), %eax
; CHECK-NEXT: leal -1(%rdi), %eax
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: movzwl %ax, %eax
; CHECK-NEXT: retq
@@ -128,8 +128,7 @@ define i64 @mul_neg_one(i64 %x) {
; CHECK-LABEL: mul_neg_one:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: shll $16, %eax
; CHECK-NEXT: subl %edi, %eax
; CHECK-NEXT: negl %eax
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: movzwl %ax, %eax
; CHECK-NEXT: retq