Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -419,6 +419,11 @@ } for (auto VT : { MVT::i8, MVT::i16, MVT::i32, MVT::i64 }) { if (VT == MVT::i64 && !Subtarget.is64Bit()) + + // Custom action for SELECT MMX and expand action for SELECT_CC MMX + setOperationAction(ISD::SELECT, MVT::x86mmx, Custom); + setOperationAction(ISD::SELECT_CC, MVT::x86mmx, Expand); + continue; setOperationAction(ISD::SELECT, VT, Custom); setOperationAction(ISD::SETCC, VT, Custom); @@ -30557,6 +30562,14 @@ // Zero extend the condition if needed. Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, TrueC->getValueType(0), Cond); + } + + // Custom action for SELECT MMX + if (VT == MVT::x86mmx) { + LHS = DAG.getBitcast(MVT::i64, LHS); + RHS = DAG.getBitcast(MVT::i64, RHS); + SDValue newSelect = DAG.getNode(ISD::SELECT, DL, MVT::i64, Cond, LHS, RHS); + return DAG.getBitcast(VT, newSelect); unsigned ShAmt = TrueC->getAPIntValue().logBase2(); Cond = DAG.getNode(ISD::SHL, DL, Cond.getValueType(), Cond, Index: test/CodeGen/X86/select-mmx.ll =================================================================== --- test/CodeGen/X86/select-mmx.ll +++ test/CodeGen/X86/select-mmx.ll @@ -0,0 +1,103 @@ +; RUN: llc -mcpu=x86_64 -march=x86_64 -mattr=+mmx < %s | FileCheck %s --check-prefix=X64 +; RUN: llc -mcpu=pentium4 -march=x86 -mattr=+mmx < %s | FileCheck %s --check-prefix=I32 + + +; From source: clang -02 +;__m64 test47(int a) +;{ +; __m64 x = (a)? (__m64)(7): (__m64)(0); +; return __builtin_ia32_psllw(x, x); +;} + +define i64 @test47(i64 %arg) local_unnamed_addr #1 { +; +; I32-LABEL: test47: # @test47 +; I32: .cfi_startproc +; I32-NEXT: # BB#0: +; I32-NEXT: subl [[ST:[$][0-9]+]], [[ESP:%e[a-z][x|i|p]]] +; I32-NEXT: .Lcfi0: +; I32-NEXT: .cfi_def_cfa_offset {{[0-9]+}} +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EAX:%e[a-z][x|i]]] +; I32-NEXT: xorl [[ECX:%e[a-z][x|i]]], [[ECX]] +; I32-NEXT: orl {{[0-9]*}}([[ESP]]), [[EAX]] +; I32-NEXT: movl $7, [[EAX]] +; I32-NEXT: cmovnel [[ECX]], [[EAX]] +; I32-NEXT: movl [[EAX]], {{[0-9]*}}([[ESP]]) +; I32-NEXT: movl $0, {{[0-9]*}}([[ESP]]) +; I32-NEXT: movq {{[0-9]+}}([[ESP]]), [[MMX0:%mm[0-9]]] +; I32-NEXT: psllw [[MMX0]], [[MMX0]] +; I32-NEXT: movq [[MMX0]], {{[0-9]*}}([[ESP]]) +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EAX:%e[a-z][x|i]]] +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EDX:%e[a-z][x|i]]] +; I32-NEXT: addl [[ST]], [[ESP]] +; I32-NEXT: retl +; +; X64-LABEL: test47: # @test47 +; X64: .cfi_startproc +; X64-NEXT: # BB#0: +; X64-NEXT: xorl [[EAX:%e[a-z][x|i]]], [[EAX:%e[a-z][x|i]]] +; X64-NEXT: testq [[RDI:%r[a-z][x|i]]], [[RDI]] +; X64-NEXT: movl $7, [[ECX:%e[a-z][x|i]]] +; X64-NEXT: cmoveq [[RCX:%r[a-z][x|i]]], [[RAX:%r[a-z][x|i]]] +; X64-NEXT: movd [[RAX]], [[MMX0:%mm[0-9]]] +; X64-NEXT: psllw [[MMX0]], [[MMX0]] +; X64-NEXT: movd [[MMX0]], [[RAX]] +; X64-NEXT: retq +; + %cond = icmp eq i64 %arg, 0 + %slct = select i1 %cond, x86_mmx bitcast (i64 7 to x86_mmx), x86_mmx bitcast (i64 0 to x86_mmx) + %psll = tail call x86_mmx @llvm.x86.mmx.psll.w(x86_mmx %slct, x86_mmx %slct) #3 + %retc = bitcast x86_mmx %psll to i64 + ret i64 %retc +} + + +; From source: clang -O2 +;__m64 test49(int a, long long n, long long m) +;{ +; __m64 x = (a)? (__m64)(n): (__m64)(m); +; return __builtin_ia32_psllw(x, x); +;} + +define i64 @test49(i64 %arg, i64 %x, i64 %y) local_unnamed_addr #1 { +; +; I32-LABEL: test49: # @test49 +; I32: .cfi_startproc +; I32-NEXT: # BB#0: +; I32-NEXT: subl [[ST:[$][0-9]+]], [[ESP:%e[a-z][x|i|p]]] +; I32-NEXT: .Lcfi1: +; I32-NEXT: .cfi_def_cfa_offset {{[0-9]+}} +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EAX:%e[a-z][x|i]]] +; I32-NEXT: leal {{[0-9]*}}([[ESP]]), [[ECX:%e[a-z][x|i]]] +; I32-NEXT: orl {{[0-9]*}}([[ESP]]), [[EAX]] +; I32-NEXT: leal {{[0-9]*}}([[ESP]]), [[EAX]] +; I32-NEXT: cmovel [[EAX]], [[ECX]] +; I32-NEXT: movq ([[ECX]]), [[MMX0:%mm[0-9]]] +; I32-NEXT: psllw [[MMX0]], [[MMX0]] +; I32-NEXT: movq [[MMX0]], {{[0-9]*}}([[ESP]]) +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EAX:%e[a-z][x|i]]] +; I32-NEXT: movl {{[0-9]*}}([[ESP]]), [[EDX:%e[a-z][x|i]]] +; I32-NEXT: addl [[ST]], [[ESP]] +; I32-NEXT: retl +; +; X64-LABEL: test49: # @test49 +; X64: .cfi_startproc +; X64-NEXT: # BB#0: +; X64-NEXT: testq [[RDI:%r[a-z][x|i]]], [[RDI]] +; X64-NEXT: cmovneq [[RDX:%r[a-z][x|i]]], [[RSI:%r[a-z][x|i]]] +; X64-NEXT: movd [[RSI]], [[MMX0:%mm[0-9]]] +; X64-NEXT: psllw [[MMX0]], [[MMX0]] +; X64-NEXT: movd [[MMX0]], [[RAX:%r[a-z][x|i]]] +; X64-NEXT: retq +; + %cond = icmp eq i64 %arg, 0 + %xmmx = bitcast i64 %x to x86_mmx + %ymmx = bitcast i64 %y to x86_mmx + %slct = select i1 %cond, x86_mmx %xmmx, x86_mmx %ymmx + %psll = tail call x86_mmx @llvm.x86.mmx.psll.w(x86_mmx %slct, x86_mmx %slct) #3 + %retc = bitcast x86_mmx %psll to i64 + ret i64 %retc +} + +declare x86_mmx @llvm.x86.mmx.psll.w(x86_mmx, x86_mmx) #2 +