diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/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,13 @@ GetSoftenedFloat(N->getOperand(0))); } +SDValue DAGTypeLegalizer::SoftenFloatRes_ARITH_FENCE(SDNode *N) { + EVT Ty = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue NewFence = DAG.getNode(ISD::ARITH_FENCE, SDLoc(N), Ty, + GetSoftenedFloat(N->getOperand(0))); + return NewFence; +} + SDValue DAGTypeLegalizer::SoftenFloatRes_MERGE_VALUES(SDNode *N, unsigned ResNo) { SDValue Op = DisintegrateMERGE_VALUES(N, ResNo); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/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; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/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); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -571,3 +571,13 @@ 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); +} diff --git a/llvm/test/CodeGen/X86/arithmetic_fence.ll b/llvm/test/CodeGen/X86/arithmetic_fence.ll --- a/llvm/test/CodeGen/X86/arithmetic_fence.ll +++ b/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>)