From: Tom Stellard Date: Wed, 24 Sep 2014 01:33:28 +0000 (+0000) Subject: R600/SI: Enable selecting SALU inside branches X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=81c6c9690a2a99ea53e642b222217fa2eef7fd92;p=oota-llvm.git R600/SI: Enable selecting SALU inside branches We can do this now that the FixSGPRLiveRanges pass is working. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218353 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp index 4fa576f8055..d8b38a233dd 100644 --- a/lib/Target/R600/AMDGPUISelDAGToDAG.cpp +++ b/lib/Target/R600/AMDGPUISelDAGToDAG.cpp @@ -79,11 +79,6 @@ private: bool isLocalLoad(const LoadSDNode *N) const; bool isRegionLoad(const LoadSDNode *N) const; - /// \returns True if the current basic block being selected is at control - /// flow depth 0. Meaning that the current block dominates the - // exit block. - bool isCFDepth0() const; - const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr); bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, @@ -605,14 +600,6 @@ bool AMDGPUDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) const { return false; } -bool AMDGPUDAGToDAGISel::isCFDepth0() const { - // FIXME: Figure out a way to use DominatorTree analysis here. - const BasicBlock *CurBlock = FuncInfo->MBB->getBasicBlock(); - const Function *Fn = FuncInfo->Fn; - return &Fn->front() == CurBlock || &Fn->back() == CurBlock; -} - - const char *AMDGPUDAGToDAGISel::getPassName() const { return "AMDGPU DAG->DAG Pattern Instruction Selection"; } @@ -718,11 +705,6 @@ SDNode *AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) { unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32; unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32; - if (!isCFDepth0()) { - Opc = IsAdd ? AMDGPU::V_ADD_I32_e32 : AMDGPU::V_SUB_I32_e32; - CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e32 : AMDGPU::V_SUBB_U32_e32; - } - SDNode *AddLo = CurDAG->getMachineNode( Opc, DL, VTList, AddLoArgs); SDValue Carry(AddLo, 1); SDNode *AddHi diff --git a/lib/Target/R600/SIInstructions.td b/lib/Target/R600/SIInstructions.td index d741c84a650..30923077538 100644 --- a/lib/Target/R600/SIInstructions.td +++ b/lib/Target/R600/SIInstructions.td @@ -33,12 +33,9 @@ def isCI : Predicate<"Subtarget.getGeneration() " ">= AMDGPUSubtarget::SEA_ISLANDS">; def HasFlatAddressSpace : Predicate<"Subtarget.hasFlatAddressSpace()">; -def isCFDepth0 : Predicate<"isCFDepth0()">; - def WAIT_FLAG : InstFlag<"printWaitFlag">; let SubtargetPredicate = isSI in { -let OtherPredicates = [isCFDepth0] in { //===----------------------------------------------------------------------===// // SMRD Instructions @@ -365,8 +362,6 @@ def S_GETREG_REGRD_B32 : SOPK_32 <0x00000014, "S_GETREG_REGRD_B32", []>; //def S_SETREG_IMM32_B32 : SOPK_32 <0x00000015, "S_SETREG_IMM32_B32", []>; //def EXP : EXP_ <0x00000000, "EXP", []>; -} // End let OtherPredicates = [isCFDepth0] - //===----------------------------------------------------------------------===// // SOPP Instructions //===----------------------------------------------------------------------===// @@ -1944,8 +1939,6 @@ def : Pat < // SOP1 Patterns //===----------------------------------------------------------------------===// -let Predicates = [isSI, isCFDepth0] in { - def : Pat < (i64 (ctpop i64:$src)), (INSERT_SUBREG (INSERT_SUBREG (i64 (IMPLICIT_DEF)), @@ -1964,8 +1957,6 @@ def : Pat < (S_ADD_U32 $src0, $src1) >; -} // Predicates = [isSI, isCFDepth0] - let Predicates = [isSI] in { //===----------------------------------------------------------------------===// diff --git a/test/CodeGen/R600/add.ll b/test/CodeGen/R600/add.ll index f62c9d6bd64..8cf43d196ec 100644 --- a/test/CodeGen/R600/add.ll +++ b/test/CodeGen/R600/add.ll @@ -141,12 +141,10 @@ entry: ret void } -; Test i64 add inside a branch. We don't allow SALU instructions inside of -; branches. -; FIXME: We are being conservative here. We could allow this in some cases. +; Test i64 add inside a branch. ; FUNC-LABEL: @add64_in_branch -; SI-CHECK-NOT: S_ADD_I32 -; SI-CHECK-NOT: S_ADDC_U32 +; SI-CHECK: S_ADD_U32 +; SI-CHECK: S_ADDC_U32 define void @add64_in_branch(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b, i64 %c) { entry: %0 = icmp eq i64 %a, 0 diff --git a/test/CodeGen/R600/ctpop.ll b/test/CodeGen/R600/ctpop.ll index fd128672a17..61d494367f6 100644 --- a/test/CodeGen/R600/ctpop.ll +++ b/test/CodeGen/R600/ctpop.ll @@ -270,28 +270,28 @@ define void @v_ctpop_i32_add_vvar_inv(i32 addrspace(1)* noalias %out, i32 addrsp ; but there are some cases when the should be allowed. ; FUNC-LABEL: @ctpop_i32_in_br -; SI: BUFFER_LOAD_DWORD [[VAL:v[0-9]+]], -; SI: V_BCNT_U32_B32_e64 [[RESULT:v[0-9]+]], [[VAL]], 0 +; SI: S_LOAD_DWORD [[VAL:s[0-9]+]], s[{{[0-9]+:[0-9]+}}], 0xd +; SI: S_BCNT1_I32_B32 [[SRESULT:s[0-9]+]], [[VAL]] +; SI: V_MOV_B32_e32 [[RESULT]], [[SRESULT]] ; SI: BUFFER_STORE_DWORD [[RESULT]], ; SI: S_ENDPGM ; EG: BCNT_INT -define void @ctpop_i32_in_br(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %cond) { +define void @ctpop_i32_in_br(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %ctpop_arg, i32 %cond) { entry: - %0 = icmp eq i32 %cond, 0 - br i1 %0, label %if, label %else + %tmp0 = icmp eq i32 %cond, 0 + br i1 %tmp0, label %if, label %else if: - %1 = load i32 addrspace(1)* %in - %2 = call i32 @llvm.ctpop.i32(i32 %1) + %tmp2 = call i32 @llvm.ctpop.i32(i32 %ctpop_arg) br label %endif else: - %3 = getelementptr i32 addrspace(1)* %in, i32 1 - %4 = load i32 addrspace(1)* %3 + %tmp3 = getelementptr i32 addrspace(1)* %in, i32 1 + %tmp4 = load i32 addrspace(1)* %tmp3 br label %endif endif: - %5 = phi i32 [%2, %if], [%4, %else] - store i32 %5, i32 addrspace(1)* %out + %tmp5 = phi i32 [%tmp2, %if], [%tmp4, %else] + store i32 %tmp5, i32 addrspace(1)* %out ret void } diff --git a/test/CodeGen/R600/ctpop64.ll b/test/CodeGen/R600/ctpop64.ll index 37a174f2ec7..76091c522ec 100644 --- a/test/CodeGen/R600/ctpop64.ll +++ b/test/CodeGen/R600/ctpop64.ll @@ -94,29 +94,28 @@ define void @v_ctpop_v4i64(<4 x i32> addrspace(1)* noalias %out, <4 x i64> addrs ; but there are some cases when the should be allowed. ; FUNC-LABEL: @ctpop_i64_in_br -; SI: V_BCNT_U32_B32_e64 [[BCNT_LO:v[0-9]+]], v{{[0-9]+}}, 0 -; SI: V_BCNT_U32_B32_e32 v[[BCNT:[0-9]+]], v{{[0-9]+}}, [[BCNT_LO]] -; SI: V_MOV_B32_e32 v[[ZERO:[0-9]+]], 0 -; SI: BUFFER_STORE_DWORDX2 v[ -; SI: [[BCNT]]:[[ZERO]]] +; SI: S_LOAD_DWORDX2 s{{\[}}[[LOVAL:[0-9]+]]:[[HIVAL:[0-9]+]]{{\]}}, s[{{[0-9]+:[0-9]+}}], 0xd +; SI: S_BCNT1_I32_B64 [[RESULT:s[0-9]+]], {{s\[}}[[LOVAL]]:[[HIVAL]]{{\]}} +; SI: V_MOV_B32_e32 v[[VLO:[0-9]+]], [[RESULT]] +; SI: V_MOV_B32_e32 v[[VHI:[0-9]+]], s[[HIVAL]] +; SI: BUFFER_STORE_DWORDX2 {{v\[}}[[VLO]]:[[VHI]]{{\]}} ; SI: S_ENDPGM -define void @ctpop_i64_in_br(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i32 %cond) { +define void @ctpop_i64_in_br(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %ctpop_arg, i32 %cond) { entry: - %0 = icmp eq i32 %cond, 0 - br i1 %0, label %if, label %else + %tmp0 = icmp eq i32 %cond, 0 + br i1 %tmp0, label %if, label %else if: - %1 = load i64 addrspace(1)* %in - %2 = call i64 @llvm.ctpop.i64(i64 %1) + %tmp2 = call i64 @llvm.ctpop.i64(i64 %ctpop_arg) br label %endif else: - %3 = getelementptr i64 addrspace(1)* %in, i32 1 - %4 = load i64 addrspace(1)* %3 + %tmp3 = getelementptr i64 addrspace(1)* %in, i32 1 + %tmp4 = load i64 addrspace(1)* %tmp3 br label %endif endif: - %5 = phi i64 [%2, %if], [%4, %else] - store i64 %5, i64 addrspace(1)* %out + %tmp5 = phi i64 [%tmp2, %if], [%tmp4, %else] + store i64 %tmp5, i64 addrspace(1)* %out ret void } diff --git a/test/CodeGen/R600/mul.ll b/test/CodeGen/R600/mul.ll index fe9c1b90edd..11de3e333ba 100644 --- a/test/CodeGen/R600/mul.ll +++ b/test/CodeGen/R600/mul.ll @@ -155,7 +155,7 @@ define void @v_mul_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addr } ; FUNC-LABEL: @mul32_in_branch -; SI: V_MUL_LO_I32 +; SI: S_MUL_I32 define void @mul32_in_branch(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %a, i32 %b, i32 %c) { entry: %0 = icmp eq i32 %a, 0 @@ -176,7 +176,7 @@ endif: } ; FUNC-LABEL: @mul64_in_branch -; SI-DAG: V_MUL_LO_I32 +; SI-DAG: S_MUL_I32 ; SI-DAG: V_MUL_HI_U32 ; SI: S_ENDPGM define void @mul64_in_branch(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b, i64 %c) { diff --git a/test/CodeGen/R600/sgpr-control-flow.ll b/test/CodeGen/R600/sgpr-control-flow.ll index 06ad24d959c..326b37ac77a 100644 --- a/test/CodeGen/R600/sgpr-control-flow.ll +++ b/test/CodeGen/R600/sgpr-control-flow.ll @@ -4,9 +4,14 @@ ; Most SALU instructions ignore control flow, so we need to make sure ; they don't overwrite values from other blocks. -; SI-NOT: S_ADD +; If the branch decision is made based on a value in an SGPR then all +; threads will execute the same code paths, so we don't need to worry +; about instructions in different blocks overwriting each other. +; SI-LABEL: @sgpr_if_else_salu_br +; SI: S_ADD +; SI: S_ADD -define void @sgpr_if_else(i32 addrspace(1)* %out, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) { +define void @sgpr_if_else_salu_br(i32 addrspace(1)* %out, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) { entry: %0 = icmp eq i32 %a, 0 br i1 %0, label %if, label %else @@ -25,3 +30,35 @@ endif: store i32 %4, i32 addrspace(1)* %out ret void } + +; The two S_ADD instructions should write to different registers, since +; different threads will take different control flow paths. + +; SI-LABEL: @sgpr_if_else_valu_br +; SI: S_ADD_I32 [[SGPR:s[0-9]+]] +; SI-NOT: S_ADD_I32 [[SGPR]] + +define void @sgpr_if_else_valu_br(i32 addrspace(1)* %out, float %a, i32 %b, i32 %c, i32 %d, i32 %e) { +entry: + %tid = call i32 @llvm.r600.read.tidig.x() #0 + %tid_f = uitofp i32 %tid to float + %tmp1 = fcmp ueq float %tid_f, 0.0 + br i1 %tmp1, label %if, label %else + +if: + %tmp2 = add i32 %b, %c + br label %endif + +else: + %tmp3 = add i32 %d, %e + br label %endif + +endif: + %tmp4 = phi i32 [%tmp2, %if], [%tmp3, %else] + store i32 %tmp4, i32 addrspace(1)* %out + ret void +} + +declare i32 @llvm.r600.read.tidig.x() #0 + +attributes #0 = { readnone } diff --git a/test/CodeGen/R600/xor.ll b/test/CodeGen/R600/xor.ll index e14bd712723..8c2c80ed195 100644 --- a/test/CodeGen/R600/xor.ll +++ b/test/CodeGen/R600/xor.ll @@ -136,8 +136,7 @@ define void @vector_not_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %in0, i64 ; use an SALU instruction for this. ; SI-CHECK-LABEL: @xor_cf -; SI-CHECK: V_XOR -; SI-CHECK: V_XOR +; SI-CHECK: S_XOR_B64 define void @xor_cf(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b) { entry: %0 = icmp eq i64 %a, 0