From 16b20d2fc5df160074ec640211cf9ac5c7881cc0 Mon Sep 17 00:00:00 2001 From: Michael Zuckerman Date: Sun, 16 Apr 2017 13:26:08 +0000 Subject: [PATCH] [X86][X86 intrinsics]Folding cmp(sub(a,b),0) into cmp(a,b) optimization This patch adds new optimization (Folding cmp(sub(a,b),0) into cmp(a,b)) to instCombineCall pass and was written specific for X86 CMP intrinsics. Differential Revision: https://reviews.llvm.org/D31398 llvm-svn: 300422 --- .../InstCombine/InstCombineCalls.cpp | 31 +++ .../InstCombine/X86FsubCmpCombine.ll | 181 ++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/X86FsubCmpCombine.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index bada71debe73..69484f47223f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2337,6 +2337,37 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { return II; break; } + case Intrinsic::x86_avx512_mask_cmp_pd_128: + case Intrinsic::x86_avx512_mask_cmp_pd_256: + case Intrinsic::x86_avx512_mask_cmp_pd_512: + case Intrinsic::x86_avx512_mask_cmp_ps_128: + case Intrinsic::x86_avx512_mask_cmp_ps_256: + case Intrinsic::x86_avx512_mask_cmp_ps_512: { + // Folding cmp(sub(a,b),0) -> cmp(a,b) and cmp(0,sub(a,b)) -> cmp(b,a) + Value *Arg0 = II->getArgOperand(0); + Value *Arg1 = II->getArgOperand(1); + bool Arg0IsZero = match(Arg0, m_Zero()); + if (Arg0IsZero) + std::swap(Arg0, Arg1); + Value *A, *B; + // This fold requires only the NINF(not +/- inf) since inf minus + // inf is nan. + // NSZ(No Signed Zeros) is not needed because zeros of any sign are + // equal for both compares. + // NNAN is not needed because nans compare the same for both compares. + // The compare intrinsic uses the above assumptions and therefore + // doesn't require additional flags. + if ((match(Arg0, m_OneUse(m_FSub(m_Value(A), m_Value(B)))) && + match(Arg1, m_Zero()) && + cast(Arg0)->getFastMathFlags().noInfs())) { + if (Arg0IsZero) + std::swap(A, B); + II->setArgOperand(0, A); + II->setArgOperand(1, B); + return II; + } + break; + } case Intrinsic::x86_avx512_mask_add_ps_512: case Intrinsic::x86_avx512_mask_div_ps_512: diff --git a/llvm/test/Transforms/InstCombine/X86FsubCmpCombine.ll b/llvm/test/Transforms/InstCombine/X86FsubCmpCombine.ll new file mode 100644 index 000000000000..fde0692d00a2 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/X86FsubCmpCombine.ll @@ -0,0 +1,181 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; The test checks the folding of cmp(sub(a,b),0) into cmp(a,b). + +define i8 @sub_compare_foldingPD128_safe(<2 x double> %a, <2 x double> %b){ +; CHECK-LABEL: @sub_compare_foldingPD128_safe( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB_SAFE:%.*]] = fsub <2 x double> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> [[SUB_SAFE]], <2 x double> zeroinitializer, i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.safe = fsub <2 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> %sub.safe , <2 x double> zeroinitializer, i32 5, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_foldingPD128(<2 x double> %a, <2 x double> %b){ +; CHECK-LABEL: @sub_compare_foldingPD128( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <2 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> %sub.i , <2 x double> zeroinitializer, i32 5, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_foldingPD256(<4 x double> %a, <4 x double> %b){ +; CHECK-LABEL: @sub_compare_foldingPD256( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.256(<4 x double> [[A:%.*]], <4 x double> [[B:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i1 = fsub ninf <4 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.256(<4 x double> %sub.i1, <4 x double> zeroinitializer, i32 5, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_foldingPD512(<8 x double> %a, <8 x double> %b){ +; CHECK-LABEL: @sub_compare_foldingPD512( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.512(<8 x double> [[A:%.*]], <8 x double> [[B:%.*]], i32 11, i8 -1, i32 4) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i2 = fsub ninf <8 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.512(<8 x double> %sub.i2, <8 x double> zeroinitializer, i32 11, i8 -1, i32 4) + ret i8 %0 +} + + +define i8 @sub_compare_foldingPS128(<4 x float> %a, <4 x float> %b){ +; CHECK-LABEL: @sub_compare_foldingPS128( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.ps.128(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], i32 12, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i3 = fsub ninf <4 x float> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.ps.128(<4 x float> %sub.i3, <4 x float> zeroinitializer, i32 12, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_foldingPS256(<8 x float> %a, <8 x float> %b){ +; CHECK-LABEL: @sub_compare_foldingPS256( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.ps.256(<8 x float> [[A:%.*]], <8 x float> [[B:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i4 = fsub ninf <8 x float> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.ps.256(<8 x float> %sub.i4, <8 x float> zeroinitializer, i32 5, i8 -1) + ret i8 %0 +} + + +define i16 @sub_compare_foldingPS512(<16 x float> %a, <16 x float> %b){ +; CHECK-LABEL: @sub_compare_foldingPS512( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.x86.avx512.mask.cmp.ps.512(<16 x float> [[A:%.*]], <16 x float> [[B:%.*]], i32 11, i16 -1, i32 4) +; CHECK-NEXT: ret i16 [[TMP0]] +; +entry: + %sub.i5 = fsub ninf <16 x float> %a, %b + %0 = tail call i16 @llvm.x86.avx512.mask.cmp.ps.512(<16 x float> %sub.i5, <16 x float> zeroinitializer, i32 11, i16 -1, i32 4) + ret i16 %0 +} + + + +define i8 @sub_compare_folding_swapPD128(<2 x double> %a, <2 x double> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPD128( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> [[B:%.*]], <2 x double> [[A:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <2 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double> zeroinitializer, <2 x double> %sub.i, i32 5, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_folding_swapPD256(<4 x double> %a, <4 x double> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPD256( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.256(<4 x double> [[B:%.*]], <4 x double> [[A:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <4 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.256(<4 x double> zeroinitializer, <4 x double> %sub.i, i32 5, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_folding_swapPD512(<8 x double> %a, <8 x double> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPD512( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.pd.512(<8 x double> [[B:%.*]], <8 x double> [[A:%.*]], i32 11, i8 -1, i32 4) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <8 x double> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.pd.512(<8 x double> zeroinitializer, <8 x double> %sub.i, i32 11, i8 -1, i32 4) + ret i8 %0 +} + + +define i8 @sub_compare_folding_swapPS128(<4 x float> %a, <4 x float> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPS128( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.ps.128(<4 x float> [[B:%.*]], <4 x float> [[A:%.*]], i32 12, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <4 x float> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.ps.128(<4 x float> zeroinitializer, <4 x float> %sub.i, i32 12, i8 -1) + ret i8 %0 +} + + +define i8 @sub_compare_folding_swapPS256(<8 x float> %a, <8 x float> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPS256( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @llvm.x86.avx512.mask.cmp.ps.256(<8 x float> [[B:%.*]], <8 x float> [[A:%.*]], i32 5, i8 -1) +; CHECK-NEXT: ret i8 [[TMP0]] +; +entry: + %sub.i = fsub ninf <8 x float> %a, %b + %0 = tail call i8 @llvm.x86.avx512.mask.cmp.ps.256(<8 x float> zeroinitializer, <8 x float> %sub.i, i32 5, i8 -1) + ret i8 %0 +} + + +define i16 @sub_compare_folding_swapPS512(<16 x float> %a, <16 x float> %b){ +; CHECK-LABEL: @sub_compare_folding_swapPS512( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i16 @llvm.x86.avx512.mask.cmp.ps.512(<16 x float> [[B:%.*]], <16 x float> [[A:%.*]], i32 11, i16 -1, i32 4) +; CHECK-NEXT: ret i16 [[TMP0]] +; +entry: + %sub.i = fsub ninf <16 x float> %a, %b + %0 = tail call i16 @llvm.x86.avx512.mask.cmp.ps.512(<16 x float> zeroinitializer, <16 x float> %sub.i, i32 11, i16 -1, i32 4) + ret i16 %0 +} + +declare i8 @llvm.x86.avx512.mask.cmp.pd.128(<2 x double>, <2 x double>, i32, i8) +declare i8 @llvm.x86.avx512.mask.cmp.pd.256(<4 x double>, <4 x double>, i32, i8) +declare i8 @llvm.x86.avx512.mask.cmp.pd.512(<8 x double>, <8 x double>, i32, i8, i32) +declare i8 @llvm.x86.avx512.mask.cmp.ps.128(<4 x float>, <4 x float>, i32, i8) +declare i8 @llvm.x86.avx512.mask.cmp.ps.256(<8 x float>, <8 x float>, i32, i8) +declare i16 @llvm.x86.avx512.mask.cmp.ps.512(<16 x float>, <16 x float>, i32, i16, i32)