Index: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1232,6 +1232,27 @@ } 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: Index: llvm/trunk/test/CodeGen/AArch64/sub1.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/sub1.ll +++ llvm/trunk/test/CodeGen/AArch64/sub1.ll @@ -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 Index: llvm/trunk/test/CodeGen/X86/bmi.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/bmi.ll +++ llvm/trunk/test/CodeGen/X86/bmi.ll @@ -813,8 +813,7 @@ 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 Index: llvm/trunk/test/CodeGen/X86/zext-demanded.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/zext-demanded.ll +++ llvm/trunk/test/CodeGen/X86/zext-demanded.ll @@ -101,7 +101,7 @@ 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 @@ ; 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