Skip to content

Commit 495d017

Browse files
committed
[SelectionDAG][X86] Preserve unpredictable metadata for conditional
branches in SelectionDAG, as well as JCCs generated by X86 backend. This builds on 09515f2, which preserves unpredictable metadata in CodeGen for `select`. This patch does it for conditional branches.
1 parent 1fa7f05 commit 495d017

File tree

8 files changed

+189
-34
lines changed

8 files changed

+189
-34
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,8 +1165,13 @@ class SelectionDAG {
11651165
SDValue N2, SDValue N3, const SDNodeFlags Flags);
11661166
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
11671167
SDValue N2, SDValue N3, SDValue N4);
1168+
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
1169+
SDValue N2, SDValue N3, SDValue N4, const SDNodeFlags Flags);
11681170
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
11691171
SDValue N2, SDValue N3, SDValue N4, SDValue N5);
1172+
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1,
1173+
SDValue N2, SDValue N3, SDValue N4, SDValue N5,
1174+
const SDNodeFlags Flags);
11701175

11711176
// Specialize again based on number of operands for nodes with a VTList
11721177
// rather than a single VT.

llvm/include/llvm/CodeGen/SwitchLoweringUtils.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,29 +137,34 @@ struct CaseBlock {
137137
SDLoc DL;
138138
DebugLoc DbgLoc;
139139

140-
// Branch weights.
140+
// Branch weights and predictability.
141141
BranchProbability TrueProb, FalseProb;
142+
bool IsUnpredictable;
142143

143144
// Constructor for SelectionDAG.
144145
CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs,
145146
const Value *cmpmiddle, MachineBasicBlock *truebb,
146147
MachineBasicBlock *falsebb, MachineBasicBlock *me, SDLoc dl,
147148
BranchProbability trueprob = BranchProbability::getUnknown(),
148-
BranchProbability falseprob = BranchProbability::getUnknown())
149+
BranchProbability falseprob = BranchProbability::getUnknown(),
150+
bool isunpredictable = false)
149151
: CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs),
150152
TrueBB(truebb), FalseBB(falsebb), ThisBB(me), DL(dl),
151-
TrueProb(trueprob), FalseProb(falseprob) {}
153+
TrueProb(trueprob), FalseProb(falseprob),
154+
IsUnpredictable(isunpredictable) {}
152155

153156
// Constructor for GISel.
154157
CaseBlock(CmpInst::Predicate pred, bool nocmp, const Value *cmplhs,
155158
const Value *cmprhs, const Value *cmpmiddle,
156159
MachineBasicBlock *truebb, MachineBasicBlock *falsebb,
157160
MachineBasicBlock *me, DebugLoc dl,
158161
BranchProbability trueprob = BranchProbability::getUnknown(),
159-
BranchProbability falseprob = BranchProbability::getUnknown())
162+
BranchProbability falseprob = BranchProbability::getUnknown(),
163+
bool isunpredictable = false)
160164
: PredInfo({pred, nocmp}), CmpLHS(cmplhs), CmpMHS(cmpmiddle),
161165
CmpRHS(cmprhs), TrueBB(truebb), FalseBB(falsebb), ThisBB(me),
162-
DbgLoc(dl), TrueProb(trueprob), FalseProb(falseprob) {}
166+
DbgLoc(dl), TrueProb(trueprob), FalseProb(falseprob),
167+
IsUnpredictable(isunpredictable) {}
163168
};
164169

165170
struct JumpTable {

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18171,7 +18171,7 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) {
1817118171
// nondeterministic jumps).
1817218172
if (N1->getOpcode() == ISD::FREEZE && N1.hasOneUse()) {
1817318173
return DAG.getNode(ISD::BRCOND, SDLoc(N), MVT::Other, Chain,
18174-
N1->getOperand(0), N2);
18174+
N1->getOperand(0), N2, N->getFlags());
1817518175
}
1817618176

1817718177
// Variant of the previous fold where there is a SETCC in between:
@@ -18220,7 +18220,8 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) {
1822018220
if (Updated)
1822118221
return DAG.getNode(
1822218222
ISD::BRCOND, SDLoc(N), MVT::Other, Chain,
18223-
DAG.getSetCC(SDLoc(N1), N1->getValueType(0), S0, S1, Cond), N2);
18223+
DAG.getSetCC(SDLoc(N1), N1->getValueType(0), S0, S1, Cond), N2,
18224+
N->getFlags());
1822418225
}
1822518226

1822618227
// If N is a constant we could fold this into a fallthrough or unconditional
@@ -18245,7 +18246,7 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) {
1824518246
HandleSDNode ChainHandle(Chain);
1824618247
if (SDValue NewN1 = rebuildSetCC(N1))
1824718248
return DAG.getNode(ISD::BRCOND, SDLoc(N), MVT::Other,
18248-
ChainHandle.getValue(), NewN1, N2);
18249+
ChainHandle.getValue(), NewN1, N2, N->getFlags());
1824918250
}
1825018251

1825118252
return SDValue();

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,14 +1065,17 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
10651065
// Create the new machine instruction.
10661066
MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), II);
10671067

1068+
// Transfer IR flags from the SDNode to the MachineInstr
1069+
MachineInstr *MI = MIB.getInstr();
1070+
const SDNodeFlags Flags = Node->getFlags();
1071+
if (Flags.hasUnpredictable())
1072+
MI->setFlag(MachineInstr::MIFlag::Unpredictable);
1073+
10681074
// Add result register values for things that are defined by this
10691075
// instruction.
10701076
if (NumResults) {
10711077
CreateVirtualRegisters(Node, MIB, II, IsClone, IsCloned, VRBaseMap);
10721078

1073-
// Transfer any IR flags from the SDNode to the MachineInstr
1074-
MachineInstr *MI = MIB.getInstr();
1075-
const SDNodeFlags Flags = Node->getFlags();
10761079
if (Flags.hasNoSignedZeros())
10771080
MI->setFlag(MachineInstr::MIFlag::FmNsz);
10781081

@@ -1105,9 +1108,6 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
11051108

11061109
if (Flags.hasNoFPExcept())
11071110
MI->setFlag(MachineInstr::MIFlag::NoFPExcept);
1108-
1109-
if (Flags.hasUnpredictable())
1110-
MI->setFlag(MachineInstr::MIFlag::Unpredictable);
11111111
}
11121112

11131113
// Emit all of the actual operands of this instruction, adding them to the

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7613,16 +7613,34 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
76137613
}
76147614

76157615
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
7616-
SDValue N1, SDValue N2, SDValue N3, SDValue N4) {
7616+
SDValue N1, SDValue N2, SDValue N3, SDValue N4,
7617+
const SDNodeFlags Flags) {
76177618
SDValue Ops[] = { N1, N2, N3, N4 };
7618-
return getNode(Opcode, DL, VT, Ops);
7619+
return getNode(Opcode, DL, VT, Ops, Flags);
7620+
}
7621+
7622+
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
7623+
SDValue N1, SDValue N2, SDValue N3, SDValue N4) {
7624+
SDNodeFlags Flags;
7625+
if (Inserter)
7626+
Flags = Inserter->getFlags();
7627+
return getNode(Opcode, DL, VT, N1, N2, N3, N4, Flags);
76197628
}
76207629

76217630
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
76227631
SDValue N1, SDValue N2, SDValue N3, SDValue N4,
7623-
SDValue N5) {
7632+
SDValue N5, const SDNodeFlags Flags) {
76247633
SDValue Ops[] = { N1, N2, N3, N4, N5 };
7625-
return getNode(Opcode, DL, VT, Ops);
7634+
return getNode(Opcode, DL, VT, Ops, Flags);
7635+
}
7636+
7637+
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
7638+
SDValue N1, SDValue N2, SDValue N3, SDValue N4,
7639+
SDValue N5) {
7640+
SDNodeFlags Flags;
7641+
if (Inserter)
7642+
Flags = Inserter->getFlags();
7643+
return getNode(Opcode, DL, VT, N1, N2, N3, N4, N5, Flags);
76267644
}
76277645

76287646
/// getStackArgumentTokenFactor - Compute a TokenFactor to force all

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,9 +2818,10 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
28182818
// je foo
28192819
// cmp D, E
28202820
// jle foo
2821+
bool IsUnpredictable = I.hasMetadata(LLVMContext::MD_unpredictable);
28212822
const Instruction *BOp = dyn_cast<Instruction>(CondVal);
28222823
if (!DAG.getTargetLoweringInfo().isJumpExpensive() && BOp &&
2823-
BOp->hasOneUse() && !I.hasMetadata(LLVMContext::MD_unpredictable)) {
2824+
BOp->hasOneUse() && !IsUnpredictable) {
28242825
Value *Vec;
28252826
const Value *BOp0, *BOp1;
28262827
Instruction::BinaryOps Opcode = (Instruction::BinaryOps)0;
@@ -2869,7 +2870,9 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
28692870

28702871
// Create a CaseBlock record representing this branch.
28712872
CaseBlock CB(ISD::SETEQ, CondVal, ConstantInt::getTrue(*DAG.getContext()),
2872-
nullptr, Succ0MBB, Succ1MBB, BrMBB, getCurSDLoc());
2873+
nullptr, Succ0MBB, Succ1MBB, BrMBB, getCurSDLoc(),
2874+
BranchProbability::getUnknown(), BranchProbability::getUnknown(),
2875+
IsUnpredictable);
28732876

28742877
// Use visitSwitchCase to actually insert the fast branch sequence for this
28752878
// cond branch.
@@ -2957,9 +2960,10 @@ void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB,
29572960
Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True);
29582961
}
29592962

2960-
SDValue BrCond = DAG.getNode(ISD::BRCOND, dl,
2961-
MVT::Other, getControlRoot(), Cond,
2962-
DAG.getBasicBlock(CB.TrueBB));
2963+
SDNodeFlags Flags;
2964+
Flags.setUnpredictable(CB.IsUnpredictable);
2965+
SDValue BrCond = DAG.getNode(ISD::BRCOND, dl, MVT::Other, getControlRoot(),
2966+
Cond, DAG.getBasicBlock(CB.TrueBB), Flags);
29632967

29642968
setValue(CurInst, BrCond);
29652969

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24827,14 +24827,14 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
2482724827

2482824828
SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8);
2482924829
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24830-
Overflow);
24830+
Overflow, Op->getFlags());
2483124831
}
2483224832

2483324833
if (LHS.getSimpleValueType().isInteger()) {
2483424834
SDValue CCVal;
2483524835
SDValue EFLAGS = emitFlagsForSetcc(LHS, RHS, CC, SDLoc(Cond), DAG, CCVal);
2483624836
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24837-
EFLAGS);
24837+
EFLAGS, Op->getFlags());
2483824838
}
2483924839

2484024840
if (CC == ISD::SETOEQ) {
@@ -24860,10 +24860,10 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
2486024860
DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS);
2486124861
SDValue CCVal = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8);
2486224862
Chain = DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest,
24863-
CCVal, Cmp);
24863+
CCVal, Cmp, Op->getFlags());
2486424864
CCVal = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8);
2486524865
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24866-
Cmp);
24866+
Cmp, Op->getFlags());
2486724867
}
2486824868
}
2486924869
} else if (CC == ISD::SETUNE) {
@@ -24872,18 +24872,18 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
2487224872
// separate test.
2487324873
SDValue Cmp = DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS);
2487424874
SDValue CCVal = DAG.getTargetConstant(X86::COND_NE, dl, MVT::i8);
24875-
Chain =
24876-
DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, Cmp);
24875+
Chain = DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24876+
Cmp, Op->getFlags());
2487724877
CCVal = DAG.getTargetConstant(X86::COND_P, dl, MVT::i8);
2487824878
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24879-
Cmp);
24879+
Cmp, Op->getFlags());
2488024880
} else {
2488124881
X86::CondCode X86Cond =
2488224882
TranslateX86CC(CC, dl, /*IsFP*/ true, LHS, RHS, DAG);
2488324883
SDValue Cmp = DAG.getNode(X86ISD::FCMP, SDLoc(Cond), MVT::i32, LHS, RHS);
2488424884
SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8);
2488524885
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24886-
Cmp);
24886+
Cmp, Op->getFlags());
2488724887
}
2488824888
}
2488924889

@@ -24894,7 +24894,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
2489424894

2489524895
SDValue CCVal = DAG.getTargetConstant(X86Cond, dl, MVT::i8);
2489624896
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24897-
Overflow);
24897+
Overflow, Op->getFlags());
2489824898
}
2489924899

2490024900
// Look past the truncate if the high bits are known zero.
@@ -24913,8 +24913,8 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
2491324913

2491424914
SDValue CCVal;
2491524915
SDValue EFLAGS = emitFlagsForSetcc(LHS, RHS, ISD::SETNE, dl, DAG, CCVal);
24916-
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,
24917-
EFLAGS);
24916+
return DAG.getNode(X86ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal, EFLAGS,
24917+
Op->getFlags());
2491824918
}
2491924919

2492024920
// Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
2+
; Make sure MIR generated for conditional branch with unpredictable metadata has unpredictable flag.
3+
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=finalize-isel < %s | FileCheck %s
4+
5+
define void @cond_branch_1(i1 %cond) {
6+
; CHECK-LABEL: name: cond_branch_1
7+
; CHECK: bb.0.entry:
8+
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
9+
; CHECK-NEXT: liveins: $edi
10+
; CHECK-NEXT: {{ $}}
11+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi
12+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr8 = COPY [[COPY]].sub_8bit
13+
; CHECK-NEXT: TEST8ri killed [[COPY1]], 1, implicit-def $eflags
14+
; CHECK-NEXT: unpredictable JCC_1 %bb.2, 4, implicit $eflags
15+
; CHECK-NEXT: JMP_1 %bb.1
16+
; CHECK-NEXT: {{ $}}
17+
; CHECK-NEXT: bb.1.then:
18+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
19+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f1, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
20+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
21+
; CHECK-NEXT: RET 0
22+
; CHECK-NEXT: {{ $}}
23+
; CHECK-NEXT: bb.2.else:
24+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
25+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f2, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
26+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
27+
; CHECK-NEXT: RET 0
28+
entry:
29+
br i1 %cond, label %then, label %else, !unpredictable !0
30+
then:
31+
call void @f1()
32+
ret void
33+
else:
34+
call void @f2()
35+
ret void
36+
}
37+
38+
define void @cond_branch_2(double %a, double %b, i32 %c, i32 %d) nounwind {
39+
; CHECK-LABEL: name: cond_branch_2
40+
; CHECK: bb.0 (%ir-block.0):
41+
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
42+
; CHECK-NEXT: liveins: $xmm0, $xmm1, $edi, $esi
43+
; CHECK-NEXT: {{ $}}
44+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $esi
45+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $edi
46+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:fr64 = COPY $xmm1
47+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:fr64 = COPY $xmm0
48+
; CHECK-NEXT: nofpexcept UCOMISDrr [[COPY2]], [[COPY3]], implicit-def $eflags, implicit $mxcsr
49+
; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 3, implicit $eflags
50+
; CHECK-NEXT: [[SUB32rr:%[0-9]+]]:gr32 = SUB32rr [[COPY1]], [[COPY]], implicit-def $eflags
51+
; CHECK-NEXT: [[SETCCr1:%[0-9]+]]:gr8 = SETCCr 6, implicit $eflags
52+
; CHECK-NEXT: [[OR8rr:%[0-9]+]]:gr8 = OR8rr [[SETCCr]], killed [[SETCCr1]], implicit-def dead $eflags
53+
; CHECK-NEXT: TEST8rr [[OR8rr]], [[OR8rr]], implicit-def $eflags
54+
; CHECK-NEXT: unpredictable JCC_1 %bb.2, 5, implicit $eflags
55+
; CHECK-NEXT: JMP_1 %bb.1
56+
; CHECK-NEXT: {{ $}}
57+
; CHECK-NEXT: bb.1.true:
58+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
59+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f1, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
60+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
61+
; CHECK-NEXT: RET 0
62+
; CHECK-NEXT: {{ $}}
63+
; CHECK-NEXT: bb.2.false:
64+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
65+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f2, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
66+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
67+
; CHECK-NEXT: RET 0
68+
%cond1 = fcmp ugt double %a, %b
69+
%cond2 = icmp ugt i32 %c, %d
70+
%cond = and i1 %cond1, %cond2
71+
br i1 %cond, label %true, label %false, !unpredictable !0
72+
true:
73+
call void @f1()
74+
ret void
75+
false:
76+
call void @f2()
77+
ret void
78+
}
79+
80+
define void @isint_branch(double %d) nounwind {
81+
; CHECK-LABEL: name: isint_branch
82+
; CHECK: bb.0 (%ir-block.0):
83+
; CHECK-NEXT: successors: %bb.1(0x50000000), %bb.2(0x30000000)
84+
; CHECK-NEXT: liveins: $xmm0
85+
; CHECK-NEXT: {{ $}}
86+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fr64 = COPY $xmm0
87+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:vr128 = COPY [[COPY]]
88+
; CHECK-NEXT: [[CVTTPD2DQrr:%[0-9]+]]:vr128 = nofpexcept CVTTPD2DQrr killed [[COPY1]], implicit $mxcsr
89+
; CHECK-NEXT: [[CVTDQ2PDrr:%[0-9]+]]:vr128 = CVTDQ2PDrr killed [[CVTTPD2DQrr]]
90+
; CHECK-NEXT: [[COPY2:%[0-9]+]]:fr64 = COPY [[CVTDQ2PDrr]]
91+
; CHECK-NEXT: nofpexcept UCOMISDrr [[COPY]], killed [[COPY2]], implicit-def $eflags, implicit $mxcsr
92+
; CHECK-NEXT: unpredictable JCC_1 %bb.2, 5, implicit $eflags
93+
; CHECK-NEXT: unpredictable JCC_1 %bb.2, 10, implicit $eflags
94+
; CHECK-NEXT: JMP_1 %bb.1
95+
; CHECK-NEXT: {{ $}}
96+
; CHECK-NEXT: bb.1.true:
97+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
98+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f1, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
99+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
100+
; CHECK-NEXT: RET 0
101+
; CHECK-NEXT: {{ $}}
102+
; CHECK-NEXT: bb.2.false:
103+
; CHECK-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
104+
; CHECK-NEXT: CALL64pcrel32 target-flags(x86-plt) @f2, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp
105+
; CHECK-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
106+
; CHECK-NEXT: RET 0
107+
%i = fptosi double %d to i32
108+
%e = sitofp i32 %i to double
109+
%c = fcmp oeq double %d, %e
110+
br i1 %c, label %true, label %false, !unpredictable !0
111+
true:
112+
call void @f1()
113+
ret void
114+
false:
115+
call void @f2()
116+
ret void
117+
}
118+
119+
declare void @f1()
120+
declare void @f2()
121+
122+
!0 = !{}

0 commit comments

Comments
 (0)