|  | ; Verify that floating-point strict signaling compares cannot be omitted | 
|  | ; even if CC already has the right value. | 
|  | ; | 
|  | ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 \ | 
|  | ; RUN:   -enable-misched=0 -no-integrated-as | FileCheck %s | 
|  | ; | 
|  | ; We need -enable-misched=0 to make sure f12 and following routines really | 
|  | ; test the compare elimination pass. | 
|  |  | 
|  |  | 
|  | declare float @llvm.fabs.f32(float %f) | 
|  |  | 
|  | ; Test addition followed by EQ, which could use the CC result of the addition. | 
|  | define float @f1(float %a, float %b, ptr %dest) #0 { | 
|  | ; CHECK-LABEL: f1: | 
|  | ; CHECK-DAG: aebr %f0, %f2 | 
|  | ; CHECK-DAG: lzer [[REG:%f[0-9]+]] | 
|  | ; CHECK-NEXT: kebr %f0, [[REG]] | 
|  | ; CHECK-NEXT: ber %r14 | 
|  | ; CHECK: br %r14 | 
|  | entry: | 
|  | %res = call float @llvm.experimental.constrained.fadd.f32( | 
|  | float %a, float %b, | 
|  | metadata !"round.dynamic", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | %cmp = call i1 @llvm.experimental.constrained.fcmps.f32( | 
|  | float %res, float 0.0, | 
|  | metadata !"oeq", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | br i1 %cmp, label %exit, label %store | 
|  |  | 
|  | store: | 
|  | store float %b, ptr %dest | 
|  | br label %exit | 
|  |  | 
|  | exit: | 
|  | ret float %res | 
|  | } | 
|  |  | 
|  | ; Test the result of LOAD POSITIVE. | 
|  | define float @f6(float %dummy, float %a, ptr %dest) #0 { | 
|  | ; CHECK-LABEL: f6: | 
|  | ; CHECK-DAG: lpdfr %f0, %f2 | 
|  | ; CHECK-DAG: lzer [[REG:%f[0-9]+]] | 
|  | ; CHECK-NEXT: kebr %f0, [[REG]] | 
|  | ; CHECK-NEXT: bhr %r14 | 
|  | ; CHECK: br %r14 | 
|  | entry: | 
|  | %res = call float @llvm.fabs.f32(float %a) #0 | 
|  | %cmp = call i1 @llvm.experimental.constrained.fcmps.f32( | 
|  | float %res, float 0.0, | 
|  | metadata !"ogt", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | br i1 %cmp, label %exit, label %store | 
|  |  | 
|  | store: | 
|  | store float %res, ptr %dest | 
|  | br label %exit | 
|  |  | 
|  | exit: | 
|  | ret float %res | 
|  | } | 
|  |  | 
|  | ; Test the result of LOAD NEGATIVE. | 
|  | define float @f7(float %dummy, float %a, ptr %dest) #0 { | 
|  | ; CHECK-LABEL: f7: | 
|  | ; CHECK-DAG: lndfr %f0, %f2 | 
|  | ; CHECK-DAG: lzer [[REG:%f[0-9]+]] | 
|  | ; CHECK-NEXT: kebr %f0, [[REG]] | 
|  | ; CHECK-NEXT: blr %r14 | 
|  | ; CHECK: br %r14 | 
|  | entry: | 
|  | %abs = call float @llvm.fabs.f32(float %a) #0 | 
|  | %res = fneg float %abs | 
|  | %cmp = call i1 @llvm.experimental.constrained.fcmps.f32( | 
|  | float %res, float 0.0, | 
|  | metadata !"olt", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | br i1 %cmp, label %exit, label %store | 
|  |  | 
|  | store: | 
|  | store float %res, ptr %dest | 
|  | br label %exit | 
|  |  | 
|  | exit: | 
|  | ret float %res | 
|  | } | 
|  |  | 
|  | ; Test the result of LOAD COMPLEMENT. | 
|  | define float @f8(float %dummy, float %a, ptr %dest) #0 { | 
|  | ; CHECK-LABEL: f8: | 
|  | ; CHECK-DAG: lcdfr %f0, %f2 | 
|  | ; CHECK-DAG: lzer [[REG:%f[0-9]+]] | 
|  | ; CHECK-NEXT: kebr %f0, [[REG]] | 
|  | ; CHECK-NEXT: bler %r14 | 
|  | ; CHECK: br %r14 | 
|  | entry: | 
|  | %res = fneg float %a | 
|  | %cmp = call i1 @llvm.experimental.constrained.fcmps.f32( | 
|  | float %res, float 0.0, | 
|  | metadata !"ole", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | br i1 %cmp, label %exit, label %store | 
|  |  | 
|  | store: | 
|  | store float %res, ptr %dest | 
|  | br label %exit | 
|  |  | 
|  | exit: | 
|  | ret float %res | 
|  | } | 
|  |  | 
|  | ; Test that LER does not get converted to LTEBR. | 
|  | define float @f12(float %dummy, float %val) #0 { | 
|  | ; CHECK-LABEL: f12: | 
|  | ; CHECK: ler %f0, %f2 | 
|  | ; CHECK-NEXT: #APP | 
|  | ; CHECK-NEXT: blah %f0 | 
|  | ; CHECK-NEXT: #NO_APP | 
|  | ; CHECK-NEXT: lzer [[REG:%f[0-9]+]] | 
|  | ; CHECK-NEXT: kebr %f2, [[REG]] | 
|  | ; CHECK-NEXT: blr %r14 | 
|  | ; CHECK: br %r14 | 
|  | entry: | 
|  | %ret = call float asm "blah $1", "=f,{f0}"(float %val) #0 | 
|  | %cmp = call i1 @llvm.experimental.constrained.fcmps.f32( | 
|  | float %val, float 0.0, | 
|  | metadata !"olt", | 
|  | metadata !"fpexcept.strict") #0 | 
|  | br i1 %cmp, label %exit, label %store | 
|  |  | 
|  | store: | 
|  | call void asm sideeffect "blah", ""() #0 | 
|  | br label %exit | 
|  |  | 
|  | exit: | 
|  | ret float %ret | 
|  | } | 
|  |  | 
|  | attributes #0 = { strictfp } | 
|  |  | 
|  | declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) | 
|  | declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) | 
|  | declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata) | 
|  | declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata) | 
|  | declare i1 @llvm.experimental.constrained.fcmps.f32(float, float, metadata, metadata) | 
|  | declare i1 @llvm.experimental.constrained.fcmps.f64(double, double, metadata, metadata) | 
|  | declare i1 @llvm.experimental.constrained.fcmps.f128(fp128, fp128, metadata, metadata) |