Index: llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -61,6 +61,7 @@ #endif llvm_unreachable("Do not know how to soften the result of this operator!"); + case ISD::ARITH_FENCE: R = SoftenFloatRes_ARITH_FENCE(N); break; case ISD::MERGE_VALUES:R = SoftenFloatRes_MERGE_VALUES(N, ResNo); break; case ISD::BITCAST: R = SoftenFloatRes_BITCAST(N); break; case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break; @@ -206,6 +207,20 @@ GetSoftenedFloat(N->getOperand(0))); } +SDValue DAGTypeLegalizer::SoftenFloatRes_ARITH_FENCE(SDNode *N) { + SDLoc dl(N); + SDValue Op = N->getOperand(0); + SDValue LHS = BitConvertToInteger(Op); + EVT ILVT = LHS.getValueType(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()); + assert(ILVT == NVT && "Wrong type!"); + + SDValue NewFence = DAG.getNode(ISD::ARITH_FENCE, dl, ILVT, LHS); + ReplaceValueWith(SDValue(N, 0), NewFence); + + return NewFence; +} + SDValue DAGTypeLegalizer::SoftenFloatRes_MERGE_VALUES(SDNode *N, unsigned ResNo) { SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -2218,6 +2218,7 @@ report_fatal_error("Do not know how to expand the result of this " "operator!"); + case ISD::ARITH_FENCE: SplitRes_ARITH_FENCE(N, Lo, Hi); break; case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break; case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -526,6 +526,7 @@ SDValue SoftenFloatRes_Unary(SDNode *N, RTLIB::Libcall LC); SDValue SoftenFloatRes_Binary(SDNode *N, RTLIB::Libcall LC); SDValue SoftenFloatRes_MERGE_VALUES(SDNode *N, unsigned ResNo); + SDValue SoftenFloatRes_ARITH_FENCE(SDNode *N); SDValue SoftenFloatRes_BITCAST(SDNode *N); SDValue SoftenFloatRes_BUILD_PAIR(SDNode *N); SDValue SoftenFloatRes_ConstantFP(SDNode *N); @@ -1019,6 +1020,7 @@ // Generic Result Splitting. void SplitRes_MERGE_VALUES(SDNode *N, unsigned ResNo, SDValue &Lo, SDValue &Hi); + void SplitRes_ARITH_FENCE (SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi); void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -571,3 +571,12 @@ Lo = DAG.getNode(ISD::FREEZE, dl, L.getValueType(), L); Hi = DAG.getNode(ISD::FREEZE, dl, H.getValueType(), H); } + +void DAGTypeLegalizer::SplitRes_ARITH_FENCE(SDNode *N, SDValue &Lo, SDValue &Hi) { + SDValue L, H; + SDLoc dl(N); + GetSplitOp(N->getOperand(0), L, H); + + Lo = DAG.getNode(ISD::ARITH_FENCE, dl, L.getValueType(), L); + Hi = DAG.getNode(ISD::ARITH_FENCE, dl, H.getValueType(), H); +} Index: llvm/test/CodeGen/X86/arithmetic_fence.ll =================================================================== --- llvm/test/CodeGen/X86/arithmetic_fence.ll +++ llvm/test/CodeGen/X86/arithmetic_fence.ll @@ -156,6 +156,58 @@ ret <2 x float> %3 } +; This @f7 IR test can be generated from flowing c test: +; +; typedef __float128 TYPE; +; TYPE foo(TYPE *qr) { +; TYPE re =__arithmetic_fence(*qr); +; return re; +;} +; +; with flowing build command: +; clang -cc1 -triple i386-pc-linux-gnu -mreassociate t.c -emit-llvm -O2 + +define dso_local fp128 @foo(fp128* nocapture readonly %qr) local_unnamed_addr{ +; X86-LABEL: foo: +; X86: # %bb.0: # %entry +; X86-NEXT: pushl %edi +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: pushl %esi +; X86-NEXT: .cfi_def_cfa_offset 12 +; X86-NEXT: .cfi_offset %esi, -12 +; X86-NEXT: .cfi_offset %edi, -8 +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl 12(%ecx), %edx +; X86-NEXT: movl 8(%ecx), %esi +; X86-NEXT: movl (%ecx), %edi +; X86-NEXT: movl 4(%ecx), %ecx +; X86-NEXT: #ARITH_FENCE +; X86-NEXT: #ARITH_FENCE +; X86-NEXT: #ARITH_FENCE +; X86-NEXT: #ARITH_FENCE +; X86-NEXT: movl %edx, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %ecx, 4(%eax) +; X86-NEXT: movl %edi, (%eax) +; X86-NEXT: popl %esi +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: popl %edi +; X86-NEXT: .cfi_def_cfa_offset 4 +; X86-NEXT: retl $4 +; +; X64-LABEL: foo: +; X64: # %bb.0: # %entry +; X64-NEXT: vmovaps (%rdi), %xmm0 +; X64-NEXT: #ARITH_FENCE +; X64-NEXT: retq +entry: + %0 = load fp128, fp128* %qr, align 16 + %1 = tail call reassoc fp128 @llvm.arithmetic.fence.f128(fp128 %0) + ret fp128 %1 +} + +declare fp128 @llvm.arithmetic.fence.f128(fp128) declare float @llvm.arithmetic.fence.f32(float) declare double @llvm.arithmetic.fence.f64(double) declare <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float>)