From: David Majnemer Date: Thu, 20 Aug 2015 09:00:56 +0000 (+0000) Subject: [X86] Fix the (shl (and (setcc_c), c1), c2) -> (and setcc_c, (c1 << c2)) fold X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=fa1aef3608ff69757a3aca53220abe1a76a4bd8e [X86] Fix the (shl (and (setcc_c), c1), c2) -> (and setcc_c, (c1 << c2)) fold We didn't check for the necessary preconditions before folding a mask/shift into a single mask. This fixes PR24516. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245544 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index a27c9f56ae4..ed347f6f9ce 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -23435,18 +23435,34 @@ static SDValue PerformSHLCombine(SDNode *N, SelectionDAG &DAG) { N1C && N0.getOpcode() == ISD::AND && N0.getOperand(1).getOpcode() == ISD::Constant) { SDValue N00 = N0.getOperand(0); - if (N00.getOpcode() == X86ISD::SETCC_CARRY || - ((N00.getOpcode() == ISD::ANY_EXTEND || - N00.getOpcode() == ISD::ZERO_EXTEND) && - N00.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY)) { - APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); - APInt ShAmt = N1C->getAPIntValue(); - Mask = Mask.shl(ShAmt); - if (Mask != 0) { - SDLoc DL(N); - return DAG.getNode(ISD::AND, DL, VT, - N00, DAG.getConstant(Mask, DL, VT)); - } + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + APInt ShAmt = N1C->getAPIntValue(); + Mask = Mask.shl(ShAmt); + bool MaskOK = false; + // We can handle cases concerning bit-widening nodes containing setcc_c if + // we carefully interrogate the mask to make sure we are semantics + // preserving. + // The transform is not safe if the result of C1 << C2 exceeds the bitwidth + // of the underlying setcc_c operation if the setcc_c was zero extended. + // Consider the following example: + // zext(setcc_c) -> i32 0x0000FFFF + // c1 -> i32 0x0000FFFF + // c2 -> i32 0x00000001 + // (shl (and (setcc_c), c1), c2) -> i32 0x0001FFFE + // (and setcc_c, (c1 << c2)) -> i32 0x0000FFFE + if (N00.getOpcode() == X86ISD::SETCC_CARRY) { + MaskOK = true; + } else if (N00.getOpcode() == ISD::SIGN_EXTEND && + N00.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) { + MaskOK = true; + } else if ((N00.getOpcode() == ISD::ZERO_EXTEND || + N00.getOpcode() == ISD::ANY_EXTEND) && + N00.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) { + MaskOK = Mask.isIntN(N00.getOperand(0).getValueSizeInBits()); + } + if (MaskOK && Mask != 0) { + SDLoc DL(N); + return DAG.getNode(ISD::AND, DL, VT, N00, DAG.getConstant(Mask, DL, VT)); } } diff --git a/test/CodeGen/X86/setcc.ll b/test/CodeGen/X86/setcc.ll index 6f1ddbdc6ac..b4847c54ffa 100644 --- a/test/CodeGen/X86/setcc.ll +++ b/test/CodeGen/X86/setcc.ll @@ -34,3 +34,23 @@ entry: %iftmp.2.0 = select i1 %0, i64 64, i64 0 ; [#uses=1] ret i64 %iftmp.2.0 } + +@v4 = common global i32 0, align 4 + +define i32 @t4(i32 %a) { +entry: +; CHECK-LABEL: t4: +; CHECK: movq _v4@GOTPCREL(%rip), %rax +; CHECK: cmpl $1, (%rax) +; CHECK: sbbl %eax, %eax +; CHECK: andl $32768, %eax +; CHECK: leal 65536(%rax,%rax), %eax + %0 = load i32, i32* @v4, align 4 + %not.tobool = icmp eq i32 %0, 0 + %conv.i = sext i1 %not.tobool to i16 + %call.lobit = lshr i16 %conv.i, 15 + %add.i.1 = add nuw nsw i16 %call.lobit, 1 + %conv4.2 = zext i16 %add.i.1 to i32 + %add = shl nuw nsw i32 %conv4.2, 16 + ret i32 %add +}