Skip to content

Commit 9a621de

Browse files
committed
[X86] Adding fp128 support for strict fcmp
Summary: Adding fp128 support for strict fcmp Reviewers: craig.topper, LiuChen3, andrew.w.kaylor, RKSimon, uweigand Subscribers: hiraditya, llvm-commits, LuoYuanke Tags: #llvm Differential Revision: https://reviews.llvm.org/D71897
1 parent 917f46d commit 9a621de

File tree

5 files changed

+164
-26
lines changed

5 files changed

+164
-26
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,6 +3032,12 @@ class TargetLowering : public TargetLoweringBase {
30323032
const SDLoc &DL, const SDValue OldLHS,
30333033
const SDValue OldRHS) const;
30343034

3035+
void softenSetCCOperands(SelectionDAG &DAG, EVT VT, SDValue &NewLHS,
3036+
SDValue &NewRHS, ISD::CondCode &CCCode,
3037+
const SDLoc &DL, const SDValue OldLHS,
3038+
const SDValue OldRHS, SDValue &Chain,
3039+
bool IsSignaling = false) const;
3040+
30353041
/// Returns a pair of (return value, chain).
30363042
/// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC.
30373043
std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC,

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,8 @@ bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) {
782782
case ISD::STRICT_LLRINT:
783783
case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break;
784784
case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
785+
case ISD::STRICT_FSETCC:
786+
case ISD::STRICT_FSETCCS:
785787
case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
786788
case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
787789
case ISD::FCOPYSIGN: Res = SoftenFloatOp_FCOPYSIGN(N); break;
@@ -931,26 +933,39 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) {
931933
}
932934

933935
SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) {
934-
SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
935-
ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
936+
bool IsStrict = N->isStrictFPOpcode();
937+
SDValue Op0 = N->getOperand(IsStrict ? 1 : 0);
938+
SDValue Op1 = N->getOperand(IsStrict ? 2 : 1);
939+
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
940+
ISD::CondCode CCCode =
941+
cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
936942

937-
EVT VT = NewLHS.getValueType();
938-
NewLHS = GetSoftenedFloat(NewLHS);
939-
NewRHS = GetSoftenedFloat(NewRHS);
940-
TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N),
941-
N->getOperand(0), N->getOperand(1));
943+
EVT VT = Op0.getValueType();
944+
SDValue NewLHS = GetSoftenedFloat(Op0);
945+
SDValue NewRHS = GetSoftenedFloat(Op1);
946+
TLI.softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, SDLoc(N), Op0, Op1,
947+
Chain, N->getOpcode() == ISD::STRICT_FSETCCS);
942948

943-
// If softenSetCCOperands returned a scalar, use it.
944-
if (!NewRHS.getNode()) {
945-
assert(NewLHS.getValueType() == N->getValueType(0) &&
946-
"Unexpected setcc expansion!");
947-
return NewLHS;
949+
// Update N to have the operands specified.
950+
if (NewRHS.getNode()) {
951+
if (IsStrict)
952+
NewLHS = DAG.getNode(ISD::SETCC, SDLoc(N), N->getValueType(0), NewLHS,
953+
NewRHS, DAG.getCondCode(CCCode));
954+
else
955+
return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
956+
DAG.getCondCode(CCCode)), 0);
948957
}
949958

950-
// Otherwise, update N to have the operands specified.
951-
return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS,
952-
DAG.getCondCode(CCCode)),
953-
0);
959+
// Otherwise, softenSetCCOperands returned a scalar, use it.
960+
assert((NewRHS.getNode() || NewLHS.getValueType() == N->getValueType(0)) &&
961+
"Unexpected setcc expansion!");
962+
963+
if (IsStrict) {
964+
ReplaceValueWith(SDValue(N, 0), NewLHS);
965+
ReplaceValueWith(SDValue(N, 1), Chain);
966+
return SDValue();
967+
}
968+
return NewLHS;
954969
}
955970

956971
SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) {

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,22 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
285285
ISD::CondCode &CCCode,
286286
const SDLoc &dl, const SDValue OldLHS,
287287
const SDValue OldRHS) const {
288+
SDValue Chain;
289+
return softenSetCCOperands(DAG, VT, NewLHS, NewRHS, CCCode, dl, OldLHS,
290+
OldRHS, Chain);
291+
}
292+
293+
void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
294+
SDValue &NewLHS, SDValue &NewRHS,
295+
ISD::CondCode &CCCode,
296+
const SDLoc &dl, const SDValue OldLHS,
297+
const SDValue OldRHS,
298+
SDValue &Chain,
299+
bool IsSignaling) const {
300+
// FIXME: Currently we cannot really respect all IEEE predicates due to libgcc
301+
// not supporting it. We can update this code when libgcc provides such
302+
// functions.
303+
288304
assert((VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f128 || VT == MVT::ppcf128)
289305
&& "Unsupported setcc type!");
290306

@@ -390,7 +406,8 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
390406
EVT OpsVT[2] = { OldLHS.getValueType(),
391407
OldRHS.getValueType() };
392408
CallOptions.setTypeListBeforeSoften(OpsVT, RetVT, true);
393-
NewLHS = makeLibCall(DAG, LC1, RetVT, Ops, CallOptions, dl).first;
409+
auto Call = makeLibCall(DAG, LC1, RetVT, Ops, CallOptions, dl, Chain);
410+
NewLHS = Call.first;
394411
NewRHS = DAG.getConstant(0, dl, RetVT);
395412

396413
CCCode = getCmpLibcallCC(LC1);
@@ -399,16 +416,22 @@ void TargetLowering::softenSetCCOperands(SelectionDAG &DAG, EVT VT,
399416
CCCode = getSetCCInverse(CCCode, RetVT);
400417
}
401418

402-
if (LC2 != RTLIB::UNKNOWN_LIBCALL) {
419+
if (LC2 == RTLIB::UNKNOWN_LIBCALL) {
420+
// Update Chain.
421+
Chain = Call.second;
422+
} else {
403423
SDValue Tmp = DAG.getNode(
404424
ISD::SETCC, dl,
405425
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), RetVT),
406426
NewLHS, NewRHS, DAG.getCondCode(CCCode));
407-
NewLHS = makeLibCall(DAG, LC2, RetVT, Ops, CallOptions, dl).first;
427+
auto Call2 = makeLibCall(DAG, LC2, RetVT, Ops, CallOptions, dl, Chain);
408428
NewLHS = DAG.getNode(
409429
ISD::SETCC, dl,
410430
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), RetVT),
411-
NewLHS, NewRHS, DAG.getCondCode(getCmpLibcallCC(LC2)));
431+
Call2.first, NewRHS, DAG.getCondCode(getCmpLibcallCC(LC2)));
432+
if (Chain)
433+
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Call.second,
434+
Call2.second);
412435
NewLHS = DAG.getNode(ISD::OR, dl, Tmp.getValueType(), Tmp, NewLHS);
413436
NewRHS = SDValue();
414437
}

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20755,7 +20755,7 @@ static std::pair<SDValue, SDValue> EmitCmp(SDValue Op0, SDValue Op1,
2075520755
const X86Subtarget &Subtarget,
2075620756
SDValue Chain, bool IsSignaling) {
2075720757
if (isNullConstant(Op1))
20758-
return std::make_pair(EmitTest(Op0, X86CC, dl, DAG, Subtarget), SDValue());
20758+
return std::make_pair(EmitTest(Op0, X86CC, dl, DAG, Subtarget), Chain);
2075920759

2076020760
EVT CmpVT = Op0.getValueType();
2076120761

@@ -21842,15 +21842,15 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
2184221842
// Handle f128 first, since one possible outcome is a normal integer
2184321843
// comparison which gets handled by emitFlagsForSetcc.
2184421844
if (Op0.getValueType() == MVT::f128) {
21845-
// FIXME: We may need a strict version of softenSetCCOperands before
21846-
// supporting f128.
21847-
assert(!IsStrict && "Unhandled strict operation!");
21848-
softenSetCCOperands(DAG, MVT::f128, Op0, Op1, CC, dl, Op0, Op1);
21845+
softenSetCCOperands(DAG, MVT::f128, Op0, Op1, CC, dl, Op0, Op1, Chain,
21846+
Op.getOpcode() == ISD::STRICT_FSETCCS);
2184921847

2185021848
// If softenSetCCOperands returned a scalar, use it.
2185121849
if (!Op1.getNode()) {
2185221850
assert(Op0.getValueType() == Op.getValueType() &&
2185321851
"Unexpected setcc expansion!");
21852+
if (IsStrict)
21853+
return DAG.getMergeValues({Op0, Chain}, dl);
2185421854
return Op0;
2185521855
}
2185621856
}

llvm/test/CodeGen/X86/fp128-libcalls-strict.ll

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,99 @@ entry:
11281128
ret i64 %round
11291129
}
11301130

1131-
attributes #0 = { strictfp }
1131+
define i64 @cmp(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
1132+
; CHECK-LABEL: cmp:
1133+
; CHECK: # %bb.0:
1134+
; CHECK-NEXT: pushq %r14
1135+
; CHECK-NEXT: pushq %rbx
1136+
; CHECK-NEXT: pushq %rax
1137+
; CHECK-NEXT: movq %rsi, %r14
1138+
; CHECK-NEXT: movq %rdi, %rbx
1139+
; CHECK-NEXT: callq __eqtf2
1140+
; CHECK-NEXT: testl %eax, %eax
1141+
; CHECK-NEXT: cmovneq %r14, %rbx
1142+
; CHECK-NEXT: movq %rbx, %rax
1143+
; CHECK-NEXT: addq $8, %rsp
1144+
; CHECK-NEXT: popq %rbx
1145+
; CHECK-NEXT: popq %r14
1146+
; CHECK-NEXT: retq
1147+
;
1148+
; X86-LABEL: cmp:
1149+
; X86: # %bb.0:
1150+
; X86-NEXT: subl $12, %esp
1151+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1152+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1153+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1154+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1155+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1156+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1157+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1158+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1159+
; X86-NEXT: calll __eqtf2
1160+
; X86-NEXT: addl $32, %esp
1161+
; X86-NEXT: testl %eax, %eax
1162+
; X86-NEXT: leal {{[0-9]+}}(%esp), %eax
1163+
; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx
1164+
; X86-NEXT: cmovel %eax, %ecx
1165+
; X86-NEXT: movl (%ecx), %eax
1166+
; X86-NEXT: movl 4(%ecx), %edx
1167+
; X86-NEXT: addl $12, %esp
1168+
; X86-NEXT: retl
1169+
%cond = call i1 @llvm.experimental.constrained.fcmp.f128(
1170+
fp128 %x, fp128 %y,
1171+
metadata !"oeq",
1172+
metadata !"fpexcept.strict") #0
1173+
%res = select i1 %cond, i64 %a, i64 %b
1174+
ret i64 %res
1175+
}
1176+
1177+
define i64 @cmps(i64 %a, i64 %b, fp128 %x, fp128 %y) #0 {
1178+
; CHECK-LABEL: cmps:
1179+
; CHECK: # %bb.0:
1180+
; CHECK-NEXT: pushq %r14
1181+
; CHECK-NEXT: pushq %rbx
1182+
; CHECK-NEXT: pushq %rax
1183+
; CHECK-NEXT: movq %rsi, %r14
1184+
; CHECK-NEXT: movq %rdi, %rbx
1185+
; CHECK-NEXT: callq __eqtf2
1186+
; CHECK-NEXT: testl %eax, %eax
1187+
; CHECK-NEXT: cmovneq %r14, %rbx
1188+
; CHECK-NEXT: movq %rbx, %rax
1189+
; CHECK-NEXT: addq $8, %rsp
1190+
; CHECK-NEXT: popq %rbx
1191+
; CHECK-NEXT: popq %r14
1192+
; CHECK-NEXT: retq
1193+
;
1194+
; X86-LABEL: cmps:
1195+
; X86: # %bb.0:
1196+
; X86-NEXT: subl $12, %esp
1197+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1198+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1199+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1200+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1201+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1202+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1203+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1204+
; X86-NEXT: pushl {{[0-9]+}}(%esp)
1205+
; X86-NEXT: calll __eqtf2
1206+
; X86-NEXT: addl $32, %esp
1207+
; X86-NEXT: testl %eax, %eax
1208+
; X86-NEXT: leal {{[0-9]+}}(%esp), %eax
1209+
; X86-NEXT: leal {{[0-9]+}}(%esp), %ecx
1210+
; X86-NEXT: cmovel %eax, %ecx
1211+
; X86-NEXT: movl (%ecx), %eax
1212+
; X86-NEXT: movl 4(%ecx), %edx
1213+
; X86-NEXT: addl $12, %esp
1214+
; X86-NEXT: retl
1215+
%cond = call i1 @llvm.experimental.constrained.fcmps.f128(
1216+
fp128 %x, fp128 %y,
1217+
metadata !"oeq",
1218+
metadata !"fpexcept.strict") #0
1219+
%res = select i1 %cond, i64 %a, i64 %b
1220+
ret i64 %res
1221+
}
1222+
1223+
attributes #0 = { nounwind strictfp }
11321224

11331225
declare fp128 @llvm.experimental.constrained.fadd.f128(fp128, fp128, metadata, metadata)
11341226
declare fp128 @llvm.experimental.constrained.fsub.f128(fp128, fp128, metadata, metadata)
@@ -1158,3 +1250,5 @@ declare i32 @llvm.experimental.constrained.lrint.i32.f128(fp128, metadata, metad
11581250
declare i64 @llvm.experimental.constrained.llrint.i64.f128(fp128, metadata, metadata)
11591251
declare i32 @llvm.experimental.constrained.lround.i32.f128(fp128, metadata)
11601252
declare i64 @llvm.experimental.constrained.llround.i64.f128(fp128, metadata)
1253+
declare i1 @llvm.experimental.constrained.fcmp.f128(fp128, fp128, metadata, metadata)
1254+
declare i1 @llvm.experimental.constrained.fcmps.f128(fp128, fp128, metadata, metadata)

0 commit comments

Comments
 (0)