Index: llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp +++ llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp @@ -170,6 +170,7 @@ if (!Subtarget.hasSSE2()) return; + const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); const LLT v16s8 = LLT::vector(16, 8); const LLT v8s16 = LLT::vector(8, 16); @@ -185,6 +186,9 @@ setAction({BinOp, Ty}, Legal); setAction({G_MUL, v8s16}, Legal); + + setAction({G_FPEXT, s64}, Legal); + setAction({G_FPEXT, 1, s32}, Legal); } void X86LegalizerInfo::setLegalizerInfoSSE41() { Index: llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp +++ llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp @@ -182,10 +182,18 @@ } unsigned NumOperands = MI.getNumOperands(); - - // Track the bank of each register, use NotFP mapping (all scalars in GPRs) SmallVector OpRegBankIdx(NumOperands); - getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); + + switch (Opc) { + case TargetOpcode::G_FPEXT: + // Instruction having only floating-point operands (all scalars in VECRReg) + getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); + break; + default: + // Track the bank of each register, use NotFP mapping (all scalars in GPRs) + getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); + break; + } // Finally construct the computed mapping. SmallVector OpdsMapping(NumOperands); Index: llvm/trunk/test/CodeGen/X86/GlobalISel/fpext-scalar.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/fpext-scalar.ll +++ llvm/trunk/test/CodeGen/X86/GlobalISel/fpext-scalar.ll @@ -0,0 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK + +define double @test(float %a) { +; CHECK-LABEL: test: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: cvtss2sd %xmm0, %xmm0 +; CHECK-NEXT: retq +entry: + %conv = fpext float %a to double + ret double %conv +} Index: llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-fpext-scalar.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-fpext-scalar.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-fpext-scalar.mir @@ -0,0 +1,33 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL +--- | + + define double @test(float %a) { + entry: + %conv = fpext float %a to double + ret double %conv + } + +... +--- +name: test +# ALL-LABEL: name: test +alignment: 4 +legalized: false +regBankSelected: false +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +# ALL: %0(s32) = COPY %xmm0 +# ALL-NEXT: %1(s64) = G_FPEXT %0(s32) +# ALL-NEXT: %xmm0 = COPY %1(s64) +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + liveins: %xmm0 + + %0(s32) = COPY %xmm0 + %1(s64) = G_FPEXT %0(s32) + %xmm0 = COPY %1(s64) + RET 0, implicit %xmm0 + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir @@ -231,7 +231,12 @@ ret float %cond } - + define double @test_fpext(float %a) { + entry: + %conv = fpext float %a to double + ret double %conv + } + ... --- name: test_add_i8 @@ -1384,3 +1389,26 @@ RET 0, implicit %xmm0 ... +--- +name: test_fpext +# CHECK-LABEL: name: test_fpext +alignment: 4 +legalized: true +regBankSelected: false +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: vecr, preferred-register: '' } +# CHECK-NEXT: - { id: 1, class: vecr, preferred-register: '' } +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } +body: | + bb.1.entry: + liveins: %xmm0 + + %0(s32) = COPY %xmm0 + %1(s64) = G_FPEXT %0(s32) + %xmm0 = COPY %1(s64) + RET 0, implicit %xmm0 + +... + Index: llvm/trunk/test/CodeGen/X86/GlobalISel/select-fpext-scalar.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/select-fpext-scalar.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-fpext-scalar.mir @@ -0,0 +1,40 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL +--- | + + define double @test(float %a) { + entry: + %conv = fpext float %a to double + ret double %conv + } + +... +--- +name: test +# ALL-LABEL: name: test +alignment: 4 +legalized: true +regBankSelected: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: fr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: fr64, preferred-register: '' } +registers: + - { id: 0, class: vecr, preferred-register: '' } + - { id: 1, class: vecr, preferred-register: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: %0 = COPY %xmm0 +# ALL-NEXT: %1 = CVTSS2SDrr %0 +# ALL-NEXT: %xmm0 = COPY %1 +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + liveins: %xmm0 + + %0(s32) = COPY %xmm0 + %1(s64) = G_FPEXT %0(s32) + %xmm0 = COPY %1(s64) + RET 0, implicit %xmm0 + +...