Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -37046,6 +37046,12 @@ SDValue Sum = ShAmt1.getOperand(0); if (auto *SumC = dyn_cast(Sum)) { SDValue ShAmt1Op1 = ShAmt1.getOperand(1); + if (ShAmt1Op1.getOpcode() == ISD::AND && + isa(ShAmt1Op1.getOperand(1)) && + ShAmt1Op1.getConstantOperandVal(1) == (Bits - 1)) { + ShMsk1 = ShAmt1Op1; + ShAmt1Op1 = ShAmt1Op1.getOperand(0); + } if (ShAmt1Op1.getOpcode() == ISD::TRUNCATE) ShAmt1Op1 = ShAmt1Op1.getOperand(0); if ((SumC->getAPIntValue() == Bits || Index: test/CodeGen/X86/shift-double-x86_64.ll =================================================================== --- test/CodeGen/X86/shift-double-x86_64.ll +++ test/CodeGen/X86/shift-double-x86_64.ll @@ -6,14 +6,10 @@ define i64 @test1(i64 %hi, i64 %lo, i64 %bits) nounwind { ; CHECK-LABEL: test1: ; CHECK: # %bb.0: +; CHECK-NEXT: movq %rdx, %rcx ; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: movl %edx, %ecx -; CHECK-NEXT: andb $63, %cl -; CHECK-NEXT: negb %cl -; CHECK-NEXT: shrq %cl, %rsi -; CHECK-NEXT: movl %edx, %ecx -; CHECK-NEXT: shlq %cl, %rax -; CHECK-NEXT: orq %rsi, %rax +; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx +; CHECK-NEXT: shldq %cl, %rsi, %rax ; CHECK-NEXT: retq %and = and i64 %bits, 63 %and64 = sub i64 64, %and @@ -26,14 +22,10 @@ define i64 @test2(i64 %hi, i64 %lo, i64 %bits) nounwind { ; CHECK-LABEL: test2: ; CHECK: # %bb.0: +; CHECK-NEXT: movq %rdx, %rcx ; CHECK-NEXT: movq %rsi, %rax -; CHECK-NEXT: movl %edx, %ecx -; CHECK-NEXT: andb $63, %cl -; CHECK-NEXT: negb %cl -; CHECK-NEXT: shlq %cl, %rdi -; CHECK-NEXT: movl %edx, %ecx -; CHECK-NEXT: shrq %cl, %rax -; CHECK-NEXT: orq %rdi, %rax +; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx +; CHECK-NEXT: shrdq %cl, %rdi, %rax ; CHECK-NEXT: retq %and = and i64 %bits, 63 %and64 = sub i64 64, %and Index: test/CodeGen/X86/shift-double.ll =================================================================== --- test/CodeGen/X86/shift-double.ll +++ test/CodeGen/X86/shift-double.ll @@ -286,30 +286,18 @@ define i32 @test11(i32 %hi, i32 %lo, i32 %bits) nounwind { ; X86-LABEL: test11: ; X86: # %bb.0: -; X86-NEXT: pushl %esi +; X86-NEXT: movb {{[0-9]+}}(%esp), %cl +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movb {{[0-9]+}}(%esp), %dl -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: andb $31, %cl -; X86-NEXT: negb %cl -; X86-NEXT: shrl %cl, %esi -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: shll %cl, %eax -; X86-NEXT: orl %esi, %eax -; X86-NEXT: popl %esi +; X86-NEXT: shldl %cl, %edx, %eax ; X86-NEXT: retl ; ; X64-LABEL: test11: ; X64: # %bb.0: -; X64-NEXT: movl %edi, %eax -; X64-NEXT: movl %edx, %ecx -; X64-NEXT: andb $31, %cl -; X64-NEXT: negb %cl -; X64-NEXT: shrl %cl, %esi ; X64-NEXT: movl %edx, %ecx -; X64-NEXT: shll %cl, %eax -; X64-NEXT: orl %esi, %eax +; X64-NEXT: movl %edi, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shldl %cl, %esi, %eax ; X64-NEXT: retq %and = and i32 %bits, 31 %and32 = sub i32 32, %and @@ -322,30 +310,18 @@ define i32 @test12(i32 %hi, i32 %lo, i32 %bits) nounwind { ; X86-LABEL: test12: ; X86: # %bb.0: -; X86-NEXT: pushl %esi +; X86-NEXT: movb {{[0-9]+}}(%esp), %cl +; X86-NEXT: movl {{[0-9]+}}(%esp), %edx ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %esi -; X86-NEXT: movb {{[0-9]+}}(%esp), %dl -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: andb $31, %cl -; X86-NEXT: negb %cl -; X86-NEXT: shll %cl, %esi -; X86-NEXT: movl %edx, %ecx -; X86-NEXT: shrl %cl, %eax -; X86-NEXT: orl %esi, %eax -; X86-NEXT: popl %esi +; X86-NEXT: shrdl %cl, %edx, %eax ; X86-NEXT: retl ; ; X64-LABEL: test12: ; X64: # %bb.0: -; X64-NEXT: movl %esi, %eax -; X64-NEXT: movl %edx, %ecx -; X64-NEXT: andb $31, %cl -; X64-NEXT: negb %cl -; X64-NEXT: shll %cl, %edi ; X64-NEXT: movl %edx, %ecx -; X64-NEXT: shrl %cl, %eax -; X64-NEXT: orl %edi, %eax +; X64-NEXT: movl %esi, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shrdl %cl, %edi, %eax ; X64-NEXT: retq %and = and i32 %bits, 31 %and32 = sub i32 32, %and