diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 5907e21065331..5ce1d4c756abb 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1850,6 +1850,35 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS, : ConstantInt::getBool(LHS->getType(), !IsAnd); } + Value *V0; + const APFloat *V0Op1, *V1Op1; + // (fcmp olt V0, V0Op1) || (fcmp olt V0, V1Op1) + // --> fcmp olt V0, max(V0Op1, V1Op1) + // (fcmp ogt V0, V0Op1) || (fcmp ogt V0, V1Op1) + // --> fcmp ogt V0, max(V0Op1, V1Op1) + // + // (fcmp olt V0, V0Op1) && (fcmp olt V0, V1Op1) + // --> fcmp olt V0, min(V0Op1, V1Op1) + // (fcmp ogt V0, V0Op1) && (fcmp ogt V0, V1Op1) + // --> fcmp ogt V0, min(V0Op1, V1Op1) + if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V0), + m_APFloat(V0Op1))) && + match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Specific(V0), + m_APFloat(V1Op1)))) { + if (*V0Op1 > *V1Op1) + return IsAnd ? RHS : LHS; + if (*V1Op1 > *V0Op1) + return IsAnd ? LHS : RHS; + } else if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V0), + m_APFloat(V0Op1))) && + match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Specific(V0), + m_APFloat(V1Op1)))) { + if (*V0Op1 < *V1Op1) + return IsAnd ? RHS : LHS; + if (*V1Op1 < *V0Op1) + return IsAnd ? LHS : RHS; + } + return nullptr; } diff --git a/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll b/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll index 3059b5b445958..f76c68919d8e1 100644 --- a/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll +++ b/llvm/test/CodeGen/AMDGPU/xor3-i1-const.ll @@ -5,10 +5,7 @@ define amdgpu_ps float @xor3_i1_const(float inreg %arg1, i32 inreg %arg2) { ; GCN-LABEL: xor3_i1_const: ; GCN: ; %bb.0: ; %main_body -; GCN-NEXT: v_mov_b32_e32 v0, 0x42640000 -; GCN-NEXT: v_cmp_lt_f32_e64 s[2:3], s0, 0 -; GCN-NEXT: v_cmp_lt_f32_e32 vcc, s0, v0 -; GCN-NEXT: s_and_b64 s[0:1], s[2:3], vcc +; GCN-NEXT: v_cmp_lt_f32_e64 s[0:1], s0, 0 ; GCN-NEXT: v_cndmask_b32_e64 v0, 1.0, 0, s[0:1] ; GCN-NEXT: ; return to shader part epilog main_body: diff --git a/llvm/test/Transforms/InstCombine/redundant-fcmp.ll b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll new file mode 100644 index 0000000000000..0f5fe9fb9a1b2 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/redundant-fcmp.ll @@ -0,0 +1,186 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @or_fcmp_redundant_or1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or1( +; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_or2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or2( +; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 2.300000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp olt double %v0, 2.300000e+00 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_or3(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or3( +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_or4(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or4( +; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp ogt double %v0, 2.300000e+00 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_or_neg1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or_neg1( +; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00 +; CHECK-NEXT: [[V3:%.*]] = or i1 [[V1]], [[V2]] +; CHECK-NEXT: ret i1 [[V3]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_or_neg2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_or_neg2( +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00 +; CHECK-NEXT: [[V3:%.*]] = or i1 [[V1]], [[V2]] +; CHECK-NEXT: ret i1 [[V3]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = or i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and1( +; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and2( +; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp olt double %v0, 2.300000e+00 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and3(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and3( +; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and4(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and4( +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 2.300000e+00 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp ogt double %v0, 2.300000e+00 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and_neg1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and_neg1( +; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0]], 1.990000e+00 +; CHECK-NEXT: [[V3:%.*]] = and i1 [[V1]], [[V2]] +; CHECK-NEXT: ret i1 [[V3]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_and_neg2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_and_neg2( +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0]], 1.990000e+00 +; CHECK-NEXT: [[V3:%.*]] = and i1 [[V1]], [[V2]] +; CHECK-NEXT: ret i1 [[V3]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = and i1 %v1, %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_select_or1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_select_or1( +; CHECK-NEXT: [[V1:%.*]] = fcmp olt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = select i1 %v1, i1 %v2, i1 false + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_select_or2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_select_or2( +; CHECK-NEXT: [[V2:%.*]] = fcmp ogt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = select i1 %v1, i1 %v2, i1 false + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_select_and1(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_select_and1( +; CHECK-NEXT: [[V2:%.*]] = fcmp olt double [[V0:%.*]], 1.990000e+00 +; CHECK-NEXT: ret i1 [[V2]] +; + %v1 = fcmp olt double %v0, 1.000000e-02 + %v2 = fcmp olt double %v0, 1.990000e+00 + %v3 = select i1 %v1, i1 true, i1 %v2 + ret i1 %v3 +} + +define i1 @or_fcmp_redundant_select_and2(double %v0) { +; CHECK-LABEL: @or_fcmp_redundant_select_and2( +; CHECK-NEXT: [[V1:%.*]] = fcmp ogt double [[V0:%.*]], 1.000000e-02 +; CHECK-NEXT: ret i1 [[V1]] +; + %v1 = fcmp ogt double %v0, 1.000000e-02 + %v2 = fcmp ogt double %v0, 1.990000e+00 + %v3 = select i1 %v1, i1 true, i1 %v2 + ret i1 %v3 +}