diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/fp128-select.ll | 98 |
3 files changed, 113 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index b6455ab51bd..692f66aeae4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -874,7 +874,7 @@ bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) { case ISD::LRINT: Res = SoftenFloatOp_LRINT(N); break; case ISD::LLRINT: Res = SoftenFloatOp_LLRINT(N); break; case ISD::SELECT: Res = SoftenFloatOp_SELECT(N); break; - case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break; + case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N, OpNo); break; case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break; case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); @@ -1090,7 +1090,19 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT(SDNode *N) { 0); } -SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) { +SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N, unsigned OpNo) { + if (OpNo == 2 || OpNo == 3) { + SDValue Op2 = GetSoftenedFloat(N->getOperand(2)); + SDValue Op3 = GetSoftenedFloat(N->getOperand(3)); + + if (Op2 == N->getOperand(2) && Op3 == N->getOperand(3)) + return SDValue(); + + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1), + Op2, Op3, N->getOperand(4)), + 0); + } + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(4))->get(); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 4fd04229fc4..d566994e7ce 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -560,7 +560,7 @@ private: SDValue SoftenFloatOp_LRINT(SDNode *N); SDValue SoftenFloatOp_LLRINT(SDNode *N); SDValue SoftenFloatOp_SELECT(SDNode *N); - SDValue SoftenFloatOp_SELECT_CC(SDNode *N); + SDValue SoftenFloatOp_SELECT_CC(SDNode *N, unsigned OpNo); SDValue SoftenFloatOp_SETCC(SDNode *N); SDValue SoftenFloatOp_STORE(SDNode *N, unsigned OpNo); diff --git a/llvm/test/CodeGen/X86/fp128-select.ll b/llvm/test/CodeGen/X86/fp128-select.ll index 134f1f38a6e..65e930e26d3 100644 --- a/llvm/test/CodeGen/X86/fp128-select.ll +++ b/llvm/test/CodeGen/X86/fp128-select.ll @@ -37,3 +37,101 @@ define void @test_select(fp128* %p, fp128* %q, i1 zeroext %c) { store fp128 %r, fp128* %q ret void } + +; The uitofp will become a select_cc. This used to crash during type +; legalization because we didn't expect the operands to need to be softened. +define fp128 @test_select_cc(fp128, fp128) { +; SSE-LABEL: test_select_cc: +; SSE: # %bb.0: # %BB0 +; SSE-NEXT: pushq %rbx +; SSE-NEXT: .cfi_def_cfa_offset 16 +; SSE-NEXT: subq $32, %rsp +; SSE-NEXT: .cfi_def_cfa_offset 48 +; SSE-NEXT: .cfi_offset %rbx, -16 +; SSE-NEXT: movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE-NEXT: movaps %xmm0, (%rsp) # 16-byte Spill +; SSE-NEXT: callq __netf2 +; SSE-NEXT: movl %eax, %ebx +; SSE-NEXT: movaps (%rsp), %xmm0 # 16-byte Reload +; SSE-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload +; SSE-NEXT: callq __eqtf2 +; SSE-NEXT: testl %eax, %eax +; SSE-NEXT: je .LBB1_1 +; SSE-NEXT: # %bb.2: # %BB0 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: jmp .LBB1_3 +; SSE-NEXT: .LBB1_1: +; SSE-NEXT: movaps {{.*}}(%rip), %xmm1 +; SSE-NEXT: .LBB1_3: # %BB0 +; SSE-NEXT: testl %ebx, %ebx +; SSE-NEXT: movaps (%rsp), %xmm0 # 16-byte Reload +; SSE-NEXT: jne .LBB1_5 +; SSE-NEXT: # %bb.4: # %BB1 +; SSE-NEXT: movaps %xmm1, %xmm0 +; SSE-NEXT: .LBB1_5: # %BB2 +; SSE-NEXT: addq $32, %rsp +; SSE-NEXT: .cfi_def_cfa_offset 16 +; SSE-NEXT: popq %rbx +; SSE-NEXT: .cfi_def_cfa_offset 8 +; SSE-NEXT: retq +; +; NOSSE-LABEL: test_select_cc: +; NOSSE: # %bb.0: # %BB0 +; NOSSE-NEXT: pushq %rbp +; NOSSE-NEXT: .cfi_def_cfa_offset 16 +; NOSSE-NEXT: pushq %r15 +; NOSSE-NEXT: .cfi_def_cfa_offset 24 +; NOSSE-NEXT: pushq %r14 +; NOSSE-NEXT: .cfi_def_cfa_offset 32 +; NOSSE-NEXT: pushq %r12 +; NOSSE-NEXT: .cfi_def_cfa_offset 40 +; NOSSE-NEXT: pushq %rbx +; NOSSE-NEXT: .cfi_def_cfa_offset 48 +; NOSSE-NEXT: .cfi_offset %rbx, -48 +; NOSSE-NEXT: .cfi_offset %r12, -40 +; NOSSE-NEXT: .cfi_offset %r14, -32 +; NOSSE-NEXT: .cfi_offset %r15, -24 +; NOSSE-NEXT: .cfi_offset %rbp, -16 +; NOSSE-NEXT: movq %rcx, %r12 +; NOSSE-NEXT: movq %rdx, %rbx +; NOSSE-NEXT: movq %rsi, %r14 +; NOSSE-NEXT: movq %rdi, %r15 +; NOSSE-NEXT: callq __netf2 +; NOSSE-NEXT: movl %eax, %ebp +; NOSSE-NEXT: movq %r15, %rdi +; NOSSE-NEXT: movq %r14, %rsi +; NOSSE-NEXT: movq %rbx, %rdx +; NOSSE-NEXT: movq %r12, %rcx +; NOSSE-NEXT: callq __eqtf2 +; NOSSE-NEXT: movl %eax, %ecx +; NOSSE-NEXT: xorl %eax, %eax +; NOSSE-NEXT: testl %ecx, %ecx +; NOSSE-NEXT: movabsq $4611404543450677248, %rdx # imm = 0x3FFF000000000000 +; NOSSE-NEXT: cmovneq %rax, %rdx +; NOSSE-NEXT: testl %ebp, %ebp +; NOSSE-NEXT: je .LBB1_2 +; NOSSE-NEXT: # %bb.1: +; NOSSE-NEXT: movq %r15, %rax +; NOSSE-NEXT: movq %r14, %rdx +; NOSSE-NEXT: .LBB1_2: # %BB2 +; NOSSE-NEXT: popq %rbx +; NOSSE-NEXT: .cfi_def_cfa_offset 40 +; NOSSE-NEXT: popq %r12 +; NOSSE-NEXT: .cfi_def_cfa_offset 32 +; NOSSE-NEXT: popq %r14 +; NOSSE-NEXT: .cfi_def_cfa_offset 24 +; NOSSE-NEXT: popq %r15 +; NOSSE-NEXT: .cfi_def_cfa_offset 16 +; NOSSE-NEXT: popq %rbp +; NOSSE-NEXT: .cfi_def_cfa_offset 8 +; NOSSE-NEXT: retq +BB0: + %a = fcmp oeq fp128 %0, %1 + %b = uitofp i1 %a to fp128 + br i1 %a, label %BB1, label %BB2 +BB1: + br label %BB2 +BB2: + %c = phi fp128 [ %0, %BB0 ], [ %b, %BB1 ] + ret fp128 %c +} |