forked from OSchip/llvm-project
[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
This commit is contained in:
parent
58ec867a3b
commit
7802be4a3d
|
@ -534,6 +534,7 @@ protected:
|
|||
bool selectCall(const User *I);
|
||||
bool selectIntrinsicCall(const IntrinsicInst *II);
|
||||
bool selectBitCast(const User *I);
|
||||
bool selectFreeze(const User *I);
|
||||
bool selectCast(const User *I, unsigned Opcode);
|
||||
bool selectExtractValue(const User *U);
|
||||
bool selectInsertValue(const User *I);
|
||||
|
|
|
@ -178,6 +178,11 @@ namespace ISD {
|
|||
/// UNDEF - An undefined node.
|
||||
UNDEF,
|
||||
|
||||
// FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or
|
||||
// is evaluated to UNDEF), or returns VAL otherwise. Note that each
|
||||
// read of UNDEF can yield different value, but FREEZE(UNDEF) cannot.
|
||||
FREEZE,
|
||||
|
||||
/// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by
|
||||
/// a Constant, which is required to be operand #1) half of the integer or
|
||||
/// float value specified as operand #0. This is only for use before
|
||||
|
|
|
@ -324,6 +324,8 @@ private:
|
|||
void Select_UNDEF(SDNode *N);
|
||||
void CannotYetSelect(SDNode *N);
|
||||
|
||||
void Select_FREEZE(SDNode *N);
|
||||
|
||||
private:
|
||||
void DoInstructionSelection();
|
||||
SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList,
|
||||
|
|
|
@ -1572,6 +1572,27 @@ bool FastISel::selectBitCast(const User *I) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FastISel::selectFreeze(const User *I) {
|
||||
Register Reg = getRegForValue(I->getOperand(0));
|
||||
if (!Reg)
|
||||
// Unhandled operand.
|
||||
return false;
|
||||
|
||||
EVT ETy = TLI.getValueType(DL, I->getOperand(0)->getType());
|
||||
if (ETy == MVT::Other || !TLI.isTypeLegal(ETy))
|
||||
// Unhandled type, bail out.
|
||||
return false;
|
||||
|
||||
MVT Ty = ETy.getSimpleVT();
|
||||
const TargetRegisterClass *TyRegClass = TLI.getRegClassFor(Ty);
|
||||
Register ResultReg = createResultReg(TyRegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(TargetOpcode::COPY), ResultReg).addReg(Reg);
|
||||
|
||||
updateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove local value instructions starting from the instruction after
|
||||
// SavedLastLocalValue to the current function insert point.
|
||||
void FastISel::removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue)
|
||||
|
@ -1913,6 +1934,9 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) {
|
|||
case Instruction::ExtractValue:
|
||||
return selectExtractValue(I);
|
||||
|
||||
case Instruction::Freeze:
|
||||
return selectFreeze(I);
|
||||
|
||||
case Instruction::PHI:
|
||||
llvm_unreachable("FastISel shouldn't visit PHI nodes!");
|
||||
|
||||
|
|
|
@ -201,6 +201,10 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
|
|||
case ISD::VECREDUCE_UMIN:
|
||||
Res = PromoteIntRes_VECREDUCE(N);
|
||||
break;
|
||||
|
||||
case ISD::FREEZE:
|
||||
Res = PromoteIntRes_FREEZE(N);
|
||||
break;
|
||||
}
|
||||
|
||||
// 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,
|
|||
return ShiftVT;
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_FREEZE(SDNode *N) {
|
||||
SDValue V = GetPromotedInteger(N->getOperand(0));
|
||||
return DAG.getNode(ISD::FREEZE, SDLoc(N),
|
||||
V.getValueType(), V);
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) {
|
||||
SDValue Op = GetPromotedInteger(N->getOperand(0));
|
||||
EVT OVT = N->getValueType(0);
|
||||
|
@ -1868,6 +1878,7 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
|
|||
case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
|
||||
case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
|
||||
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
|
||||
case ISD::FREEZE: SplitRes_FREEZE(N, Lo, Hi); break;
|
||||
|
||||
case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break;
|
||||
case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break;
|
||||
|
|
|
@ -309,6 +309,7 @@ private:
|
|||
SDValue PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N);
|
||||
SDValue PromoteIntRes_FP_TO_XINT(SDNode *N);
|
||||
SDValue PromoteIntRes_FP_TO_FP16(SDNode *N);
|
||||
SDValue PromoteIntRes_FREEZE(SDNode *N);
|
||||
SDValue PromoteIntRes_INT_EXTEND(SDNode *N);
|
||||
SDValue PromoteIntRes_LOAD(LoadSDNode *N);
|
||||
SDValue PromoteIntRes_MLOAD(MaskedLoadSDNode *N);
|
||||
|
@ -961,6 +962,7 @@ private:
|
|||
void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||
void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||
void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||
void SplitRes_FREEZE (SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||
|
||||
void SplitVSETCC(const SDNode *N);
|
||||
|
||||
|
|
|
@ -558,3 +558,12 @@ void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi) {
|
|||
Lo = DAG.getUNDEF(LoVT);
|
||||
Hi = DAG.getUNDEF(HiVT);
|
||||
}
|
||||
|
||||
void DAGTypeLegalizer::SplitRes_FREEZE(SDNode *N, SDValue &Lo, SDValue &Hi) {
|
||||
SDValue L, H;
|
||||
SDLoc dl(N);
|
||||
GetSplitOp(N->getOperand(0), L, H);
|
||||
|
||||
Lo = DAG.getNode(ISD::FREEZE, dl, L.getValueType(), L);
|
||||
Hi = DAG.getNode(ISD::FREEZE, dl, H.getValueType(), H);
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
|
|||
case ISD::FLOG2:
|
||||
case ISD::FNEARBYINT:
|
||||
case ISD::FNEG:
|
||||
case ISD::FREEZE:
|
||||
case ISD::FP_EXTEND:
|
||||
case ISD::FP_TO_SINT:
|
||||
case ISD::FP_TO_UINT:
|
||||
|
@ -879,6 +880,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
|
|||
case ISD::FLOG2:
|
||||
case ISD::FNEARBYINT:
|
||||
case ISD::FNEG:
|
||||
case ISD::FREEZE:
|
||||
case ISD::FP_EXTEND:
|
||||
case ISD::FP_ROUND:
|
||||
case ISD::FP_TO_SINT:
|
||||
|
@ -2831,6 +2833,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
|
|||
case ISD::CTTZ:
|
||||
case ISD::CTTZ_ZERO_UNDEF:
|
||||
case ISD::FNEG:
|
||||
case ISD::FREEZE:
|
||||
case ISD::FCANONICALIZE:
|
||||
Res = WidenVecRes_Unary(N);
|
||||
break;
|
||||
|
|
|
@ -10690,6 +10690,22 @@ void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) {
|
|||
}
|
||||
|
||||
void SelectionDAGBuilder::visitFreeze(const FreezeInst &I) {
|
||||
SDValue N = getValue(I.getOperand(0));
|
||||
setValue(&I, N);
|
||||
SDNodeFlags Flags;
|
||||
|
||||
SDValue Op = getValue(I.getOperand(0));
|
||||
if (I.getOperand(0)->getType()->isAggregateType()) {
|
||||
EVT VT = Op.getValueType();
|
||||
SmallVector<SDValue, 1> Values;
|
||||
for (unsigned i = 0; i < Op.getNumOperands(); ++i) {
|
||||
SDValue Arg(Op.getNode(), i);
|
||||
SDValue UnNodeValue = DAG.getNode(ISD::FREEZE, getCurSDLoc(), VT, Arg, Flags);
|
||||
Values.push_back(UnNodeValue);
|
||||
}
|
||||
SDValue MergedValue = DAG.getMergeValues(Values, getCurSDLoc());
|
||||
setValue(&I, MergedValue);
|
||||
} else {
|
||||
SDValue UnNodeValue = DAG.getNode(ISD::FREEZE, getCurSDLoc(), Op.getValueType(),
|
||||
Op, Flags);
|
||||
setValue(&I, UnNodeValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -392,6 +392,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
|||
case ISD::GC_TRANSITION_START: return "gc_transition.start";
|
||||
case ISD::GC_TRANSITION_END: return "gc_transition.end";
|
||||
case ISD::GET_DYNAMIC_AREA_OFFSET: return "get.dynamic.area.offset";
|
||||
case ISD::FREEZE: return "freeze";
|
||||
|
||||
// Bit manipulation
|
||||
case ISD::ABS: return "abs";
|
||||
|
|
|
@ -2290,6 +2290,14 @@ void SelectionDAGISel::Select_UNDEF(SDNode *N) {
|
|||
CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF, N->getValueType(0));
|
||||
}
|
||||
|
||||
void SelectionDAGISel::Select_FREEZE(SDNode *N) {
|
||||
// TODO: We don't have FREEZE pseudo-instruction in MachineInstr-level now.
|
||||
// If FREEZE instruction is added later, the code below must be changed as
|
||||
// well.
|
||||
CurDAG->SelectNodeTo(N, TargetOpcode::COPY, N->getValueType(0),
|
||||
N->getOperand(0));
|
||||
}
|
||||
|
||||
/// GetVBR - decode a vbr encoding whose top bit is set.
|
||||
LLVM_ATTRIBUTE_ALWAYS_INLINE static inline uint64_t
|
||||
GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) {
|
||||
|
@ -2826,6 +2834,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
|
|||
case ISD::UNDEF:
|
||||
Select_UNDEF(NodeToMatch);
|
||||
return;
|
||||
case ISD::FREEZE:
|
||||
Select_FREEZE(NodeToMatch);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!NodeToMatch->isMachineOpcode() && "Node already selected!");
|
||||
|
|
|
@ -1657,7 +1657,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
|
|||
case ExtractValue: return ISD::MERGE_VALUES;
|
||||
case InsertValue: return ISD::MERGE_VALUES;
|
||||
case LandingPad: return 0;
|
||||
case Freeze: return 0;
|
||||
case Freeze: return ISD::FREEZE;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unknown instruction type encountered!");
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=SDAG
|
||||
; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-unknown-linux | FileCheck %s --check-prefix=FAST
|
||||
|
||||
define i32 @freeze(i32 %t) {
|
||||
; SDAG-LABEL: freeze:
|
||||
; SDAG: # %bb.0:
|
||||
; SDAG-NEXT: movl $10, %eax
|
||||
; SDAG-NEXT: xorl %edi, %eax
|
||||
; SDAG-NEXT: retq
|
||||
;
|
||||
; FAST-LABEL: freeze:
|
||||
; FAST: # %bb.0:
|
||||
; FAST-NEXT: movl $10, %eax
|
||||
; FAST-NEXT: xorl %edi, %eax
|
||||
; FAST-NEXT: retq
|
||||
%1 = freeze i32 %t
|
||||
%2 = freeze i32 10
|
||||
%3 = xor i32 %1, %2
|
||||
ret i32 %3
|
||||
}
|
|
@ -99,6 +99,11 @@ define void @load_store_i1(i1* %p, i1* %q) nounwind {
|
|||
ret void
|
||||
}
|
||||
|
||||
define void @freeze_i32(i32 %x) {
|
||||
%t = freeze i32 %x
|
||||
ret void
|
||||
}
|
||||
|
||||
@crash_test1x = external global <2 x i32>, align 8
|
||||
|
||||
define void @crash_test1() nounwind ssp {
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; Make sure that seldag legalization works correctly for freeze instruction.
|
||||
; RUN: llc -mtriple=i386-apple-darwin < %s 2>&1 | FileCheck %s
|
||||
|
||||
define i64 @expand(i32 %x) {
|
||||
; CHECK-LABEL: expand:
|
||||
; CHECK: ## %bb.0:
|
||||
; CHECK-NEXT: movl $303174162, %eax ## imm = 0x12121212
|
||||
; CHECK-NEXT: movl $875836468, %ecx ## imm = 0x34343434
|
||||
; CHECK-NEXT: movl $1448498774, %edx ## imm = 0x56565656
|
||||
; CHECK-NEXT: xorl %eax, %edx
|
||||
; CHECK-NEXT: movl $2021161080, %eax ## imm = 0x78787878
|
||||
; CHECK-NEXT: xorl %ecx, %eax
|
||||
; CHECK-NEXT: retl
|
||||
%y1 = freeze i64 1302123111658042420 ; 0x1212121234343434
|
||||
%y2 = freeze i64 6221254864647256184 ; 0x5656565678787878
|
||||
%t2 = xor i64 %y1, %y2
|
||||
ret i64 %t2
|
||||
}
|
||||
|
||||
|
||||
define <2 x i64> @expand_vec(i32 %x) nounwind {
|
||||
; CHECK-LABEL: expand_vec:
|
||||
; CHECK: ## %bb.0:
|
||||
; CHECK-NEXT: pushl %ebx
|
||||
; CHECK-NEXT: pushl %edi
|
||||
; CHECK-NEXT: pushl %esi
|
||||
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||||
; CHECK-NEXT: movl $16843009, %ecx ## imm = 0x1010101
|
||||
; CHECK-NEXT: movl $589505315, %edx ## imm = 0x23232323
|
||||
; CHECK-NEXT: movl $303174162, %esi ## imm = 0x12121212
|
||||
; CHECK-NEXT: movl $875836468, %edi ## imm = 0x34343434
|
||||
; CHECK-NEXT: movl $1162167621, %ebx ## imm = 0x45454545
|
||||
; CHECK-NEXT: xorl %ecx, %ebx
|
||||
; CHECK-NEXT: movl $1734829927, %ecx ## imm = 0x67676767
|
||||
; CHECK-NEXT: xorl %edx, %ecx
|
||||
; CHECK-NEXT: movl $1448498774, %edx ## imm = 0x56565656
|
||||
; CHECK-NEXT: xorl %esi, %edx
|
||||
; CHECK-NEXT: movl $2021161080, %esi ## imm = 0x78787878
|
||||
; CHECK-NEXT: xorl %edi, %esi
|
||||
; CHECK-NEXT: movl %ebx, 12(%eax)
|
||||
; CHECK-NEXT: movl %ecx, 8(%eax)
|
||||
; CHECK-NEXT: movl %edx, 4(%eax)
|
||||
; CHECK-NEXT: movl %esi, (%eax)
|
||||
; CHECK-NEXT: popl %esi
|
||||
; CHECK-NEXT: popl %edi
|
||||
; CHECK-NEXT: popl %ebx
|
||||
; CHECK-NEXT: retl $4
|
||||
; <0x1212121234343434, 0x101010123232323>
|
||||
%y1 = freeze <2 x i64> <i64 1302123111658042420, i64 72340173410738979>
|
||||
; <0x5656565678787878, 0x4545454567676767>
|
||||
%y2 = freeze <2 x i64> <i64 6221254864647256184, i64 4991471926399952743>
|
||||
%t2 = xor <2 x i64> %y1, %y2
|
||||
ret <2 x i64> %t2
|
||||
}
|
||||
|
||||
define i10 @promote() {
|
||||
; CHECK-LABEL: promote:
|
||||
; CHECK: ## %bb.0:
|
||||
; CHECK-NEXT: movw $682, %cx ## imm = 0x2AA
|
||||
; CHECK-NEXT: movw $992, %ax ## imm = 0x3E0
|
||||
; CHECK-NEXT: addl %ecx, %eax
|
||||
; CHECK-NEXT: ## kill: def $ax killed $ax killed $eax
|
||||
; CHECK-NEXT: retl
|
||||
%a = freeze i10 682
|
||||
%b = freeze i10 992
|
||||
%res = add i10 %a, %b
|
||||
ret i10 %res
|
||||
}
|
||||
|
||||
define <2 x i10> @promote_vec() {
|
||||
; CHECK-LABEL: promote_vec:
|
||||
; CHECK: ## %bb.0:
|
||||
; CHECK-NEXT: movw $125, %ax
|
||||
; CHECK-NEXT: movw $682, %cx ## imm = 0x2AA
|
||||
; CHECK-NEXT: movw $393, %dx ## imm = 0x189
|
||||
; CHECK-NEXT: addl %eax, %edx
|
||||
; CHECK-NEXT: movw $992, %ax ## imm = 0x3E0
|
||||
; CHECK-NEXT: addl %ecx, %eax
|
||||
; CHECK-NEXT: ## kill: def $ax killed $ax killed $eax
|
||||
; CHECK-NEXT: ## kill: def $dx killed $dx killed $edx
|
||||
; CHECK-NEXT: retl
|
||||
%a = freeze <2 x i10> <i10 682, i10 125>
|
||||
%b = freeze <2 x i10> <i10 992, i10 393>
|
||||
%res = add <2 x i10> %a, %b
|
||||
ret <2 x i10> %res
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s 2>&1 | FileCheck %s --check-prefix=X86ASM
|
||||
|
||||
%struct.T = type { i32, i32 }
|
||||
|
||||
define i32 @freeze_int() {
|
||||
; X86ASM-LABEL: freeze_int:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: imull %eax, %eax
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze i32 undef
|
||||
%t1 = mul i32 %y1, %y1
|
||||
ret i32 %t1
|
||||
}
|
||||
|
||||
define i5 @freeze_int2() {
|
||||
; X86ASM-LABEL: freeze_int2:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: mulb %al
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze i5 undef
|
||||
%t1 = mul i5 %y1, %y1
|
||||
ret i5 %t1
|
||||
}
|
||||
|
||||
define float @freeze_float() {
|
||||
; X86ASM-LABEL: freeze_float:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: addss %xmm0, %xmm0
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze float undef
|
||||
%t1 = fadd float %y1, %y1
|
||||
ret float %t1
|
||||
}
|
||||
|
||||
define <2 x i32> @freeze_ivec() {
|
||||
; X86ASM-LABEL: freeze_ivec:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: paddd %xmm0, %xmm0
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze <2 x i32> undef
|
||||
%t1 = add <2 x i32> %y1, %y1
|
||||
ret <2 x i32> %t1
|
||||
}
|
||||
|
||||
define i8* @freeze_ptr() {
|
||||
; X86ASM-LABEL: freeze_ptr:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: addq $4, %rax
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze i8* undef
|
||||
%t1 = getelementptr i8, i8* %y1, i64 4
|
||||
ret i8* %t1
|
||||
}
|
||||
|
||||
define i32 @freeze_struct() {
|
||||
; X86ASM-LABEL: freeze_struct:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: addl %eax, %eax
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze %struct.T undef
|
||||
%v1 = extractvalue %struct.T %y1, 0
|
||||
%v2 = extractvalue %struct.T %y1, 1
|
||||
%t1 = add i32 %v1, %v2
|
||||
ret i32 %t1
|
||||
}
|
||||
|
||||
define i32 @freeze_anonstruct() {
|
||||
; X86ASM-LABEL: freeze_anonstruct:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: addl %eax, %eax
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze {i32, i32} undef
|
||||
%v1 = extractvalue {i32, i32} %y1, 0
|
||||
%v2 = extractvalue {i32, i32} %y1, 1
|
||||
%t1 = add i32 %v1, %v2
|
||||
ret i32 %t1
|
||||
}
|
||||
|
||||
define i64 @freeze_array() {
|
||||
; X86ASM-LABEL: freeze_array:
|
||||
; X86ASM: # %bb.0:
|
||||
; X86ASM-NEXT: addq %rax, %rax
|
||||
; X86ASM-NEXT: retq
|
||||
%y1 = freeze [2 x i64] undef
|
||||
%v1 = extractvalue [2 x i64] %y1, 0
|
||||
%v2 = extractvalue [2 x i64] %y1, 1
|
||||
%t1 = add i64 %v1, %v2
|
||||
ret i64 %t1
|
||||
}
|
Loading…
Reference in New Issue