Skip to content

Commit 7802be4

Browse files
committed
[SelDag] Add FREEZE
Summary: - Add FREEZE node to SelDag - Lower FreezeInst (in IR) to FREEZE node - Add Legalization for FREEZE node Reviewers: qcolombet, bogner, efriedma, lebedev.ri, nlopes, craig.topper, arsenm Reviewed By: lebedev.ri Subscribers: wdng, xbolva00, Petar.Avramovic, liuz, lkail, dylanmckay, hiraditya, Jim, arsenm, craig.topper, RKSimon, spatel, lebedev.ri, regehr, trentxintong, nlopes, mkuper, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D29014
1 parent 58ec867 commit 7802be4

16 files changed

+291
-3
lines changed

llvm/include/llvm/CodeGen/FastISel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ class FastISel {
534534
bool selectCall(const User *I);
535535
bool selectIntrinsicCall(const IntrinsicInst *II);
536536
bool selectBitCast(const User *I);
537+
bool selectFreeze(const User *I);
537538
bool selectCast(const User *I, unsigned Opcode);
538539
bool selectExtractValue(const User *U);
539540
bool selectInsertValue(const User *I);

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ namespace ISD {
178178
/// UNDEF - An undefined node.
179179
UNDEF,
180180

181+
// FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or
182+
// is evaluated to UNDEF), or returns VAL otherwise. Note that each
183+
// read of UNDEF can yield different value, but FREEZE(UNDEF) cannot.
184+
FREEZE,
185+
181186
/// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by
182187
/// a Constant, which is required to be operand #1) half of the integer or
183188
/// float value specified as operand #0. This is only for use before

llvm/include/llvm/CodeGen/SelectionDAGISel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ class SelectionDAGISel : public MachineFunctionPass {
324324
void Select_UNDEF(SDNode *N);
325325
void CannotYetSelect(SDNode *N);
326326

327+
void Select_FREEZE(SDNode *N);
328+
327329
private:
328330
void DoInstructionSelection();
329331
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList,

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,27 @@ bool FastISel::selectBitCast(const User *I) {
15721572
return true;
15731573
}
15741574

1575+
bool FastISel::selectFreeze(const User *I) {
1576+
Register Reg = getRegForValue(I->getOperand(0));
1577+
if (!Reg)
1578+
// Unhandled operand.
1579+
return false;
1580+
1581+
EVT ETy = TLI.getValueType(DL, I->getOperand(0)->getType());
1582+
if (ETy == MVT::Other || !TLI.isTypeLegal(ETy))
1583+
// Unhandled type, bail out.
1584+
return false;
1585+
1586+
MVT Ty = ETy.getSimpleVT();
1587+
const TargetRegisterClass *TyRegClass = TLI.getRegClassFor(Ty);
1588+
Register ResultReg = createResultReg(TyRegClass);
1589+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1590+
TII.get(TargetOpcode::COPY), ResultReg).addReg(Reg);
1591+
1592+
updateValueMap(I, ResultReg);
1593+
return true;
1594+
}
1595+
15751596
// Remove local value instructions starting from the instruction after
15761597
// SavedLastLocalValue to the current function insert point.
15771598
void FastISel::removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue)
@@ -1913,6 +1934,9 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) {
19131934
case Instruction::ExtractValue:
19141935
return selectExtractValue(I);
19151936

1937+
case Instruction::Freeze:
1938+
return selectFreeze(I);
1939+
19161940
case Instruction::PHI:
19171941
llvm_unreachable("FastISel shouldn't visit PHI nodes!");
19181942

llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
201201
case ISD::VECREDUCE_UMIN:
202202
Res = PromoteIntRes_VECREDUCE(N);
203203
break;
204+
205+
case ISD::FREEZE:
206+
Res = PromoteIntRes_FREEZE(N);
207+
break;
204208
}
205209

206210
// If the result is null then the sub-method took care of registering it.
@@ -401,6 +405,12 @@ static EVT getShiftAmountTyForConstant(EVT VT, const TargetLowering &TLI,
401405
return ShiftVT;
402406
}
403407

408+
SDValue DAGTypeLegalizer::PromoteIntRes_FREEZE(SDNode *N) {
409+
SDValue V = GetPromotedInteger(N->getOperand(0));
410+
return DAG.getNode(ISD::FREEZE, SDLoc(N),
411+
V.getValueType(), V);
412+
}
413+
404414
SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) {
405415
SDValue Op = GetPromotedInteger(N->getOperand(0));
406416
EVT OVT = N->getValueType(0);
@@ -1868,6 +1878,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
18681878
case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
18691879
case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
18701880
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
1881+
case ISD::FREEZE: SplitRes_FREEZE(N, Lo, Hi); break;
18711882

18721883
case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break;
18731884
case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break;

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
309309
SDValue PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N);
310310
SDValue PromoteIntRes_FP_TO_XINT(SDNode *N);
311311
SDValue PromoteIntRes_FP_TO_FP16(SDNode *N);
312+
SDValue PromoteIntRes_FREEZE(SDNode *N);
312313
SDValue PromoteIntRes_INT_EXTEND(SDNode *N);
313314
SDValue PromoteIntRes_LOAD(LoadSDNode *N);
314315
SDValue PromoteIntRes_MLOAD(MaskedLoadSDNode *N);
@@ -961,6 +962,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
961962
void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi);
962963
void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi);
963964
void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi);
965+
void SplitRes_FREEZE (SDNode *N, SDValue &Lo, SDValue &Hi);
964966

965967
void SplitVSETCC(const SDNode *N);
966968

llvm/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,3 +558,12 @@ void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi) {
558558
Lo = DAG.getUNDEF(LoVT);
559559
Hi = DAG.getUNDEF(HiVT);
560560
}
561+
562+
void DAGTypeLegalizer::SplitRes_FREEZE(SDNode *N, SDValue &Lo, SDValue &Hi) {
563+
SDValue L, H;
564+
SDLoc dl(N);
565+
GetSplitOp(N->getOperand(0), L, H);
566+
567+
Lo = DAG.getNode(ISD::FREEZE, dl, L.getValueType(), L);
568+
Hi = DAG.getNode(ISD::FREEZE, dl, H.getValueType(), H);
569+
}

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
8989
case ISD::FLOG2:
9090
case ISD::FNEARBYINT:
9191
case ISD::FNEG:
92+
case ISD::FREEZE:
9293
case ISD::FP_EXTEND:
9394
case ISD::FP_TO_SINT:
9495
case ISD::FP_TO_UINT:
@@ -879,6 +880,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
879880
case ISD::FLOG2:
880881
case ISD::FNEARBYINT:
881882
case ISD::FNEG:
883+
case ISD::FREEZE:
882884
case ISD::FP_EXTEND:
883885
case ISD::FP_ROUND:
884886
case ISD::FP_TO_SINT:
@@ -2831,6 +2833,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
28312833
case ISD::CTTZ:
28322834
case ISD::CTTZ_ZERO_UNDEF:
28332835
case ISD::FNEG:
2836+
case ISD::FREEZE:
28342837
case ISD::FCANONICALIZE:
28352838
Res = WidenVecRes_Unary(N);
28362839
break;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10690,6 +10690,22 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
1069010690
}
1069110691

1069210692
void SelectionDAGBuilder::visitFreeze(const FreezeInst &I) {
10693-
SDValue N = getValue(I.getOperand(0));
10694-
setValue(&I, N);
10693+
SDNodeFlags Flags;
10694+
10695+
SDValue Op = getValue(I.getOperand(0));
10696+
if (I.getOperand(0)->getType()->isAggregateType()) {
10697+
EVT VT = Op.getValueType();
10698+
SmallVector<SDValue, 1> Values;
10699+
for (unsigned i = 0; i < Op.getNumOperands(); ++i) {
10700+
SDValue Arg(Op.getNode(), i);
10701+
SDValue UnNodeValue = DAG.getNode(ISD::FREEZE, getCurSDLoc(), VT, Arg, Flags);
10702+
Values.push_back(UnNodeValue);
10703+
}
10704+
SDValue MergedValue = DAG.getMergeValues(Values, getCurSDLoc());
10705+
setValue(&I, MergedValue);
10706+
} else {
10707+
SDValue UnNodeValue = DAG.getNode(ISD::FREEZE, getCurSDLoc(), Op.getValueType(),
10708+
Op, Flags);
10709+
setValue(&I, UnNodeValue);
10710+
}
1069510711
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
392392
case ISD::GC_TRANSITION_START: return "gc_transition.start";
393393
case ISD::GC_TRANSITION_END: return "gc_transition.end";
394394
case ISD::GET_DYNAMIC_AREA_OFFSET: return "get.dynamic.area.offset";
395+
case ISD::FREEZE: return "freeze";
395396

396397
// Bit manipulation
397398
case ISD::ABS: return "abs";

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,6 +2290,14 @@ void SelectionDAGISel::Select_UNDEF(SDNode *N) {
22902290
CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF, N->getValueType(0));
22912291
}
22922292

2293+
void SelectionDAGISel::Select_FREEZE(SDNode *N) {
2294+
// TODO: We don't have FREEZE pseudo-instruction in MachineInstr-level now.
2295+
// If FREEZE instruction is added later, the code below must be changed as
2296+
// well.
2297+
CurDAG->SelectNodeTo(N, TargetOpcode::COPY, N->getValueType(0),
2298+
N->getOperand(0));
2299+
}
2300+
22932301
/// GetVBR - decode a vbr encoding whose top bit is set.
22942302
LLVM_ATTRIBUTE_ALWAYS_INLINE static inline uint64_t
22952303
GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) {
@@ -2826,6 +2834,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
28262834
case ISD::UNDEF:
28272835
Select_UNDEF(NodeToMatch);
28282836
return;
2837+
case ISD::FREEZE:
2838+
Select_FREEZE(NodeToMatch);
2839+
return;
28292840
}
28302841

28312842
assert(!NodeToMatch->isMachineOpcode() && "Node already selected!");

llvm/lib/CodeGen/TargetLoweringBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1657,7 +1657,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
16571657
case ExtractValue: return ISD::MERGE_VALUES;
16581658
case InsertValue: return ISD::MERGE_VALUES;
16591659
case LandingPad: return 0;
1660-
case Freeze: return 0;
1660+
case Freeze: return ISD::FREEZE;
16611661
}
16621662

16631663
llvm_unreachable("Unknown instruction type encountered!");
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=SDAG
3+
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=FAST
4+
5+
define i32 @freeze(i32 %t) {
6+
; SDAG-LABEL: freeze:
7+
; SDAG: # %bb.0:
8+
; SDAG-NEXT: movl $10, %eax
9+
; SDAG-NEXT: xorl %edi, %eax
10+
; SDAG-NEXT: retq
11+
;
12+
; FAST-LABEL: freeze:
13+
; FAST: # %bb.0:
14+
; FAST-NEXT: movl $10, %eax
15+
; FAST-NEXT: xorl %edi, %eax
16+
; FAST-NEXT: retq
17+
%1 = freeze i32 %t
18+
%2 = freeze i32 10
19+
%3 = xor i32 %1, %2
20+
ret i32 %3
21+
}

llvm/test/CodeGen/X86/fast-isel.ll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ define void @load_store_i1(i1* %p, i1* %q) nounwind {
9999
ret void
100100
}
101101

102+
define void @freeze_i32(i32 %x) {
103+
%t = freeze i32 %x
104+
ret void
105+
}
106+
102107
@crash_test1x = external global <2 x i32>, align 8
103108

104109
define void @crash_test1() nounwind ssp {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; Make sure that seldag legalization works correctly for freeze instruction.
3+
; RUN: llc -mtriple=i386-apple-darwin < %s 2>&1 | FileCheck %s
4+
5+
define i64 @expand(i32 %x) {
6+
; CHECK-LABEL: expand:
7+
; CHECK: ## %bb.0:
8+
; CHECK-NEXT: movl $303174162, %eax ## imm = 0x12121212
9+
; CHECK-NEXT: movl $875836468, %ecx ## imm = 0x34343434
10+
; CHECK-NEXT: movl $1448498774, %edx ## imm = 0x56565656
11+
; CHECK-NEXT: xorl %eax, %edx
12+
; CHECK-NEXT: movl $2021161080, %eax ## imm = 0x78787878
13+
; CHECK-NEXT: xorl %ecx, %eax
14+
; CHECK-NEXT: retl
15+
%y1 = freeze i64 1302123111658042420 ; 0x1212121234343434
16+
%y2 = freeze i64 6221254864647256184 ; 0x5656565678787878
17+
%t2 = xor i64 %y1, %y2
18+
ret i64 %t2
19+
}
20+
21+
22+
define <2 x i64> @expand_vec(i32 %x) nounwind {
23+
; CHECK-LABEL: expand_vec:
24+
; CHECK: ## %bb.0:
25+
; CHECK-NEXT: pushl %ebx
26+
; CHECK-NEXT: pushl %edi
27+
; CHECK-NEXT: pushl %esi
28+
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
29+
; CHECK-NEXT: movl $16843009, %ecx ## imm = 0x1010101
30+
; CHECK-NEXT: movl $589505315, %edx ## imm = 0x23232323
31+
; CHECK-NEXT: movl $303174162, %esi ## imm = 0x12121212
32+
; CHECK-NEXT: movl $875836468, %edi ## imm = 0x34343434
33+
; CHECK-NEXT: movl $1162167621, %ebx ## imm = 0x45454545
34+
; CHECK-NEXT: xorl %ecx, %ebx
35+
; CHECK-NEXT: movl $1734829927, %ecx ## imm = 0x67676767
36+
; CHECK-NEXT: xorl %edx, %ecx
37+
; CHECK-NEXT: movl $1448498774, %edx ## imm = 0x56565656
38+
; CHECK-NEXT: xorl %esi, %edx
39+
; CHECK-NEXT: movl $2021161080, %esi ## imm = 0x78787878
40+
; CHECK-NEXT: xorl %edi, %esi
41+
; CHECK-NEXT: movl %ebx, 12(%eax)
42+
; CHECK-NEXT: movl %ecx, 8(%eax)
43+
; CHECK-NEXT: movl %edx, 4(%eax)
44+
; CHECK-NEXT: movl %esi, (%eax)
45+
; CHECK-NEXT: popl %esi
46+
; CHECK-NEXT: popl %edi
47+
; CHECK-NEXT: popl %ebx
48+
; CHECK-NEXT: retl $4
49+
; <0x1212121234343434, 0x101010123232323>
50+
%y1 = freeze <2 x i64> <i64 1302123111658042420, i64 72340173410738979>
51+
; <0x5656565678787878, 0x4545454567676767>
52+
%y2 = freeze <2 x i64> <i64 6221254864647256184, i64 4991471926399952743>
53+
%t2 = xor <2 x i64> %y1, %y2
54+
ret <2 x i64> %t2
55+
}
56+
57+
define i10 @promote() {
58+
; CHECK-LABEL: promote:
59+
; CHECK: ## %bb.0:
60+
; CHECK-NEXT: movw $682, %cx ## imm = 0x2AA
61+
; CHECK-NEXT: movw $992, %ax ## imm = 0x3E0
62+
; CHECK-NEXT: addl %ecx, %eax
63+
; CHECK-NEXT: ## kill: def $ax killed $ax killed $eax
64+
; CHECK-NEXT: retl
65+
%a = freeze i10 682
66+
%b = freeze i10 992
67+
%res = add i10 %a, %b
68+
ret i10 %res
69+
}
70+
71+
define <2 x i10> @promote_vec() {
72+
; CHECK-LABEL: promote_vec:
73+
; CHECK: ## %bb.0:
74+
; CHECK-NEXT: movw $125, %ax
75+
; CHECK-NEXT: movw $682, %cx ## imm = 0x2AA
76+
; CHECK-NEXT: movw $393, %dx ## imm = 0x189
77+
; CHECK-NEXT: addl %eax, %edx
78+
; CHECK-NEXT: movw $992, %ax ## imm = 0x3E0
79+
; CHECK-NEXT: addl %ecx, %eax
80+
; CHECK-NEXT: ## kill: def $ax killed $ax killed $eax
81+
; CHECK-NEXT: ## kill: def $dx killed $dx killed $edx
82+
; CHECK-NEXT: retl
83+
%a = freeze <2 x i10> <i10 682, i10 125>
84+
%b = freeze <2 x i10> <i10 992, i10 393>
85+
%res = add <2 x i10> %a, %b
86+
ret <2 x i10> %res
87+
}

0 commit comments

Comments
 (0)