Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5378,6 +5378,17 @@ return false; SDValue NegOp1 = Neg.getOperand(1); + // If the src operand for subtraction is trunc/sign/zext/any-extended, strip it + // for truncation, this is, + // trunc((trunc(i32 -> i16) - i16) -> i16) == trunc((i32 - i16) -> i16) + bool NegOp1Peel = false; + if (NegOp1.getOpcode() == ISD::SIGN_EXTEND || + NegOp1.getOpcode() == ISD::ZERO_EXTEND || + NegOp1.getOpcode() == ISD::ANY_EXTEND || + NegOp1.getOpcode() == ISD::TRUNCATE) { + NegOp1Peel = true; + } + // On the RHS of [A], if Pos is Pos' & (EltSize - 1), just replace Pos with // Pos'. The truncation is redundant for the purpose of the equality. if (MaskLoBits && Pos.getOpcode() == ISD::AND) { @@ -5401,7 +5412,7 @@ // // (because "x & Mask" is a truncation and distributes through subtraction). APInt Width; - if (Pos == NegOp1) + if (Pos == NegOp1 || (NegOp1Peel && Pos == NegOp1.getOperand(0))) Width = NegC->getAPIntValue(); // Check for cases where Pos has the form (add NegOp1, PosC) for some PosC. Index: test/CodeGen/X86/rot16.ll =================================================================== --- test/CodeGen/X86/rot16.ll +++ test/CodeGen/X86/rot16.ll @@ -13,7 +13,7 @@ ; X64-LABEL: foo: ; X64: # %bb.0: ; X64-NEXT: movl %edx, %ecx -; X64-NEXT: shldw %cl, %di, %di +; X64-NEXT: rolw %cl, %di ; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %t0 = shl i16 %x, %z @@ -56,7 +56,7 @@ ; X64-LABEL: un: ; X64: # %bb.0: ; X64-NEXT: movl %edx, %ecx -; X64-NEXT: shrdw %cl, %di, %di +; X64-NEXT: rorw %cl, %di ; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %t0 = lshr i16 %x, %z