
This patch generalizes https://github.com/llvm/llvm-project/issues/81027 to handle pattern `and/or (fcmp ord/uno X, 0), (fcmp pred fabs(X), Y)`. Alive2: https://alive2.llvm.org/ce/z/tsgUrz The correctness is straightforward because `fcmp ord/uno X, 0.0` is equivalent to `fcmp ord/uno fabs(X), 0.0`. We may generalize it to handle fneg as well. Address comment https://github.com/llvm/llvm-project/pull/116065#pullrequestreview-2434796846
494 lines
15 KiB
LLVM
494 lines
15 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
; Cycle through commuted variants where one operand of fcmp ord/uno is
|
|
; known not-a-NAN and the other is repeated in the logically-connected fcmp.
|
|
|
|
declare float @llvm.fabs.f32(float)
|
|
declare void @llvm.assume(i1 noundef)
|
|
|
|
define i1 @ord1(float %x, float %y) {
|
|
; CHECK-LABEL: @ord1(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord float 0.0, %x
|
|
%cmp2 = fcmp ord float %x, %y
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ord1_assume(float %x, float %y, float %not.nan) {
|
|
; CHECK-LABEL: @ord1_assume(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%ord = fcmp ord float %not.nan, 0.0
|
|
call void @llvm.assume(i1 %ord)
|
|
%cmp1 = fcmp ord float %not.nan, %x
|
|
%cmp2 = fcmp ord float %x, %y
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ord2(double %x, double %y) {
|
|
; CHECK-LABEL: @ord2(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord double 42.0, %x
|
|
%cmp2 = fcmp ord double %y, %x
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @ord3(<2 x float> %x, <2 x float> %y) {
|
|
; CHECK-LABEL: @ord3(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord <2 x float> %x, zeroinitializer
|
|
%cmp2 = fcmp ord <2 x float> %x, %y
|
|
%r = and <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @ord3_assume(float %x, float %y, float %not.nan) {
|
|
; CHECK-LABEL: @ord3_assume(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%ord = fcmp ord float %not.nan, 0.0
|
|
call void @llvm.assume(i1 %ord)
|
|
%cmp1 = fcmp ord float %x, %not.nan
|
|
%cmp2 = fcmp ord float %x, %y
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @ord4(<2 x double> %x, <2 x double> %y) {
|
|
; CHECK-LABEL: @ord4(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ord <2 x double> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord <2 x double> %x, <double 42.0, double 42.0>
|
|
%cmp2 = fcmp ord <2 x double> %y, %x
|
|
%r = and <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @ord5(float %x, float %y) {
|
|
; CHECK-LABEL: @ord5(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%nnan = fdiv nnan float %x, %y
|
|
%cmp1 = fcmp ord float %x, %y
|
|
%cmp2 = fcmp ord float %nnan, %x
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ord5_assume(float %x, float %y, float %nnan) {
|
|
; CHECK-LABEL: @ord5_assume(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[NNAN:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%ord = fcmp ord float %nnan, 0.0
|
|
call void @llvm.assume(i1 %ord)
|
|
%cmp1 = fcmp ord float %x, %y
|
|
%cmp2 = fcmp ord float %nnan, %x
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ord6(double %x, double %y) {
|
|
; CHECK-LABEL: @ord6(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp ord double %y, %x
|
|
%cmp2 = fcmp ord double 42.0, %x
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @ord6_assume(double %x, double %y, double %not.nan) {
|
|
; CHECK-LABEL: @ord6_assume(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord double [[NOT_NAN:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%ord = fcmp ord double %not.nan, 0.0
|
|
call void @llvm.assume(i1 %ord)
|
|
%cmp1 = fcmp ord double %y, %x
|
|
%cmp2 = fcmp ord double %not.nan, %x
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @ord7(<2 x float> %x, <2 x float> %y) {
|
|
; CHECK-LABEL: @ord7(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp ord <2 x float> %x, %y
|
|
%cmp2 = fcmp ord <2 x float> %x, zeroinitializer
|
|
%r = and <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @ord7_assume(float %x, float %y, float %not.nan) {
|
|
; CHECK-LABEL: @ord7_assume(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[ORD]])
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%ord = fcmp ord float %not.nan, 0.0
|
|
call void @llvm.assume(i1 %ord)
|
|
%cmp1 = fcmp ord float %x, %y
|
|
%cmp2 = fcmp ord float %x, %not.nan
|
|
%r = and i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @ord8(<2 x double> %x, <2 x double> %y) {
|
|
; CHECK-LABEL: @ord8(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord <2 x double> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp ord <2 x double> %y, %x
|
|
%cmp2 = fcmp ord <2 x double> %x, <double 0.0, double 42.0>
|
|
%r = and <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @uno1(float %x, float %y) {
|
|
; CHECK-LABEL: @uno1(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp uno float 0.0, %x
|
|
%cmp2 = fcmp uno float %x, %y
|
|
%r = or i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @uno2(double %x, double %y) {
|
|
; CHECK-LABEL: @uno2(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno double [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp uno double 42.0, %x
|
|
%cmp2 = fcmp uno double %y, %x
|
|
%r = or i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @uno3(<2 x float> %x, <2 x float> %y) {
|
|
; CHECK-LABEL: @uno3(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp uno <2 x float> %x, zeroinitializer
|
|
%cmp2 = fcmp uno <2 x float> %x, %y
|
|
%r = or <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @uno4(<2 x double> %x, <2 x double> %y) {
|
|
; CHECK-LABEL: @uno4(
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uno <2 x double> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp uno <2 x double> %x, <double 42.0, double 42.0>
|
|
%cmp2 = fcmp uno <2 x double> %y, %x
|
|
%r = or <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @uno5(float %x, float %y) {
|
|
; CHECK-LABEL: @uno5(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp uno float %x, %y
|
|
%cmp2 = fcmp uno float 0.0, %x
|
|
%r = or i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define i1 @uno6(double %x, double %y) {
|
|
; CHECK-LABEL: @uno6(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno double [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp uno double %y, %x
|
|
%cmp2 = fcmp uno double 42.0, %x
|
|
%r = or i1 %cmp1, %cmp2
|
|
ret i1 %r
|
|
}
|
|
|
|
define <2 x i1> @uno7(<2 x float> %x, <2 x float> %y) {
|
|
; CHECK-LABEL: @uno7(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
|
;
|
|
%nnan = fdiv nnan <2 x float> %x, %y
|
|
%cmp1 = fcmp uno <2 x float> %x, %y
|
|
%cmp2 = fcmp uno <2 x float> %x, %nnan
|
|
%r = or <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define <2 x i1> @uno8(<2 x double> %x, <2 x double> %y) {
|
|
; CHECK-LABEL: @uno8(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x double> [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
|
|
;
|
|
%cmp1 = fcmp uno <2 x double> %y, %x
|
|
%cmp2 = fcmp uno <2 x double> %x, <double 0x7ff0000000000000, double 42.0>
|
|
%r = or <2 x i1> %cmp1, %cmp2
|
|
ret <2 x i1> %r
|
|
}
|
|
|
|
define i1 @olt_implies_ord(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_ord(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[OLT]]
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%olt = fcmp olt float %x, %y
|
|
%ret = and i1 %olt, %ord
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @olt_implies_ord_commuted1(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_ord_commuted1(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[OLT]]
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%olt = fcmp olt float %y, %x
|
|
%ret = and i1 %olt, %ord
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @olt_implies_ord_commuted2(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_ord_commuted2(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[OLT]]
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%olt = fcmp olt float %x, %y
|
|
%ret = and i1 %ord, %olt
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @olt_implies_ord_commuted3(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_ord_commuted3(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
|
|
; CHECK-NEXT: ret i1 [[OLT]]
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%olt = fcmp olt float %y, %x
|
|
%ret = and i1 %ord, %olt
|
|
ret i1 %ret
|
|
}
|
|
|
|
define <2 x i1> @olt_implies_ord_vec(<2 x float> %x, <2 x float> %y) {
|
|
; CHECK-LABEL: @olt_implies_ord_vec(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt <2 x float> [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret <2 x i1> [[OLT]]
|
|
;
|
|
%ord = fcmp ord <2 x float> %x, zeroinitializer
|
|
%olt = fcmp olt <2 x float> %x, %y
|
|
%ret = and <2 x i1> %ord, %olt
|
|
ret <2 x i1> %ret
|
|
}
|
|
|
|
define i1 @ord_implies_ord(float %x, float %y) {
|
|
; CHECK-LABEL: @ord_implies_ord(
|
|
; CHECK-NEXT: [[ORD2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[ORD2]]
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%ord2 = fcmp ord float %x, %y
|
|
%ret = and i1 %ord, %ord2
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @olt_implies_uno(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_uno(
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
%uno = fcmp uno float %x, 0.000000e+00
|
|
%olt = fcmp olt float %x, %y
|
|
%ret = and i1 %olt, %uno
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @ult_implies_uno(float %x, float %y) {
|
|
; CHECK-LABEL: @ult_implies_uno(
|
|
; CHECK-NEXT: [[ULT:%.*]] = fcmp ult float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[ULT]]
|
|
;
|
|
%uno = fcmp uno float %x, 0.000000e+00
|
|
%ult = fcmp ult float %x, %y
|
|
%ret = or i1 %ult, %uno
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @uno_implies_uno(float %x, float %y) {
|
|
; CHECK-LABEL: @uno_implies_uno(
|
|
; CHECK-NEXT: [[UNO2:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[UNO2]]
|
|
;
|
|
%uno = fcmp uno float %x, 0.000000e+00
|
|
%uno2 = fcmp uno float %x, %y
|
|
%ret = or i1 %uno, %uno2
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @ult_implies_ord(float %x, float %y) {
|
|
; CHECK-LABEL: @ult_implies_ord(
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%ord = fcmp ord float %x, 0.000000e+00
|
|
%ult = fcmp ult float %x, %y
|
|
%ret = or i1 %ult, %ord
|
|
ret i1 %ret
|
|
}
|
|
|
|
; TODO: %cmp1 is false implies %cmp3 is true
|
|
define float @test_ord_implies_uno(float %x) {
|
|
; CHECK-LABEL: @test_ord_implies_uno(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[CMP3:%.*]] = fcmp uno float [[X]], 0.000000e+00
|
|
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
|
|
; CHECK-NEXT: [[RET:%.*]] = select i1 [[SEL]], float 0.000000e+00, float [[X]]
|
|
; CHECK-NEXT: ret float [[RET]]
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%cmp2 = fcmp olt float %x, 0.000000e+00
|
|
%cmp3 = fcmp uno float %x, 0.000000e+00
|
|
%sel = select i1 %cmp1, i1 %cmp2, i1 %cmp3
|
|
%ret = select i1 %sel, float 0.000000e+00, float %x
|
|
ret float %ret
|
|
}
|
|
|
|
; Negative tests
|
|
|
|
define i1 @olt_implies_ord_fail(float %x, float %y, float %z) {
|
|
; CHECK-LABEL: @olt_implies_ord_fail(
|
|
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord float [[X:%.*]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[RET:%.*]] = and i1 [[OLT]], [[ORD]]
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
;
|
|
%ord = fcmp ord float %x, %z
|
|
%olt = fcmp olt float %x, %y
|
|
%ret = and i1 %olt, %ord
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @ult_implies_uno_and(float %x, float %y) {
|
|
; CHECK-LABEL: @ult_implies_uno_and(
|
|
; CHECK-NEXT: [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[ULT:%.*]] = fcmp ult float [[X]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[RET:%.*]] = and i1 [[ULT]], [[UNO]]
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
;
|
|
%uno = fcmp uno float %x, 0.000000e+00
|
|
%ult = fcmp ult float %x, %y
|
|
%ret = and i1 %ult, %uno
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @olt_implies_olt_fail(float %x, float %y) {
|
|
; CHECK-LABEL: @olt_implies_olt_fail(
|
|
; CHECK-NEXT: [[OLT:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[OLT2:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[RET:%.*]] = and i1 [[OLT]], [[OLT2]]
|
|
; CHECK-NEXT: ret i1 [[RET]]
|
|
;
|
|
%olt = fcmp olt float %x, 0.000000e+00
|
|
%olt2 = fcmp olt float %x, %y
|
|
%ret = and i1 %olt, %olt2
|
|
ret i1 %ret
|
|
}
|
|
|
|
define i1 @and_ord_olt_abs(float %x, float %y) {
|
|
; CHECK-LABEL: @and_ord_olt_abs(
|
|
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSX]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%absx = call float @llvm.fabs.f32(float %x)
|
|
%cmp2 = fcmp olt float %absx, %y
|
|
%and = and i1 %cmp1, %cmp2
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @and_ord_olt_abs_commuted1(float %x, float %y) {
|
|
; CHECK-LABEL: @and_ord_olt_abs_commuted1(
|
|
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[Y:%.*]], [[ABSX]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%absx = call float @llvm.fabs.f32(float %x)
|
|
%cmp2 = fcmp olt float %y, %absx
|
|
%and = and i1 %cmp1, %cmp2
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @and_ord_olt_abs_commuted2(float %x, float %y) {
|
|
; CHECK-LABEL: @and_ord_olt_abs_commuted2(
|
|
; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSX]], [[Y:%.*]]
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%absx = call float @llvm.fabs.f32(float %x)
|
|
%cmp2 = fcmp olt float %absx, %y
|
|
%and = and i1 %cmp2, %cmp1
|
|
ret i1 %and
|
|
}
|
|
|
|
define i1 @or_ord_ult_abs(float %x, float %y) {
|
|
; CHECK-LABEL: @or_ord_ult_abs(
|
|
; CHECK-NEXT: ret i1 true
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%absx = call float @llvm.fabs.f32(float %x)
|
|
%cmp2 = fcmp ult float %absx, %y
|
|
%or = or i1 %cmp1, %cmp2
|
|
ret i1 %or
|
|
}
|
|
|
|
define i1 @and_ord_olt_absz(float %x, float %y, float %z) {
|
|
; CHECK-LABEL: @and_ord_olt_absz(
|
|
; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
|
|
; CHECK-NEXT: [[ABSZ:%.*]] = call float @llvm.fabs.f32(float [[Z:%.*]])
|
|
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[ABSZ]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
|
; CHECK-NEXT: ret i1 [[AND]]
|
|
;
|
|
%cmp1 = fcmp ord float %x, 0.000000e+00
|
|
%absz = call float @llvm.fabs.f32(float %z)
|
|
%cmp2 = fcmp olt float %absz, %y
|
|
%and = and i1 %cmp1, %cmp2
|
|
ret i1 %and
|
|
}
|