[llvm] r245544 - [X86] Fix the (shl (and (setcc_c), c1), c2) -> (and setcc_c, (c1 << c2)) fold
David Majnemer via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 02:00:57 PDT 2015
Author: majnemer
Date: Thu Aug 20 04:00:56 2015
New Revision: 245544
URL: http://llvm.org/viewvc/llvm-project?rev=245544&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
llvm/trunk/test/CodeGen/X86/setcc.ll
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=245544&r1=245543&r2=245544&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu Aug 20 04:00:56 2015
@@ -23435,18 +23435,34 @@ static SDValue PerformSHLCombine(SDNode
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<ConstantSDNode>(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<ConstantSDNode>(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));
}
}
Modified: llvm/trunk/test/CodeGen/X86/setcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=245544&r1=245543&r2=245544&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/setcc.ll (original)
+++ llvm/trunk/test/CodeGen/X86/setcc.ll Thu Aug 20 04:00:56 2015
@@ -34,3 +34,23 @@ entry:
%iftmp.2.0 = select i1 %0, i64 64, i64 0 ; <i64> [#uses=1]
ret i64 %iftmp.2.0
}
+
+ at v4 = common global i32 0, align 4
+
+define i32 @t4(i32 %a) {
+entry:
+; CHECK-LABEL: t4:
+; CHECK: movq _v4 at 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
+}
More information about the llvm-commits
mailing list