Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -5072,12 +5072,12 @@ // value that has its last 6 bits set, we can safely remove the AND operation. SDValue N1 = N->getOperand(1); if (N1.getOpcode() == ISD::AND) { - auto *AndMask = dyn_cast(N1.getOperand(1)); + SDValue AndMaskOp = N1->getOperand(1); + auto *AndMask = dyn_cast(AndMaskOp); + auto AmtVal = AndMask->getZExtValue(); // The AND mask is constant if (AndMask) { - auto AmtVal = AndMask->getZExtValue(); - // Bottom 6 bits are set if ((AmtVal & 0x3f) == 0x3f) { SDValue AndOp = N1->getOperand(0); @@ -5099,6 +5099,25 @@ return Replace; } + + // We can't remove the AND, but we can use NILL here (normally we would + // use NILF). Only keep the last 16 bits of the mask. + } else if (AmtVal >> 16 != 0) { + SDValue AndOp = N1->getOperand(0); + + auto NewMask = DAG.getConstant(AndMask->getZExtValue() & 0x0000ffff, + SDLoc(AndMaskOp), + AndMaskOp.getValueType()); + + auto NewAnd = DAG.getNode(N1.getOpcode(), SDLoc(N1), N1.getValueType(), + AndOp, NewMask); + + SDValue Replace = DAG.getNode(N->getOpcode(), SDLoc(N), + N->getValueType(0), N->getOperand(0), + NewAnd); + DCI.AddToWorklist(Replace.getNode()); + + return Replace; } } } Index: test/CodeGen/SystemZ/shift-11.ll =================================================================== --- test/CodeGen/SystemZ/shift-11.ll +++ test/CodeGen/SystemZ/shift-11.ll @@ -61,3 +61,25 @@ %shift = shl i64 %a, %and ret i64 %shift } + +; Test shift with negative 32-bit value. +define i32 @f8(i32 %a, i32 %sh, i32 %test) { +; CHECK-LABEL: f8: +; CHECK: nill %r3, 65529 +; CHECK: sll %r2, 0(%r3) + %and = and i32 %sh, -7 + %shift = shl i32 %a, %and + + ret i32 %shift +} + +; Test shift with negative 64-bit value. +define i64 @f9(i64 %a, i64 %sh, i64 %test) { +; CHECK-LABEL: f9: +; CHECK: nill %r3, 65529 +; CHECK: sllg %r2, %r2, 0(%r3) + %and = and i64 %sh, -7 + %shift = shl i64 %a, %and + + ret i64 %shift +}