[llvm] r218529 - R600/SI: Don't move operands that are required to be SGPRs

Matt Arsenault Matthew.Arsenault at amd.com
Fri Sep 26 10:54:52 PDT 2014


Author: arsenm
Date: Fri Sep 26 12:54:52 2014
New Revision: 218529

URL: http://llvm.org/viewvc/llvm-project?rev=218529&view=rev
Log:
R600/SI: Don't move operands that are required to be SGPRs

e.g. v_cndmask_b32 requires the condition operand be an SGPR.
If one of the source operands were an SGPR, that would be considered
the one SGPR use and the condition operand would be illegally moved.

Modified:
    llvm/trunk/lib/Target/R600/SIInstrInfo.cpp
    llvm/trunk/test/CodeGen/R600/v_cndmask.ll

Modified: llvm/trunk/lib/Target/R600/SIInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/R600/SIInstrInfo.cpp?rev=218529&r1=218528&r2=218529&view=diff
==============================================================================
--- llvm/trunk/lib/Target/R600/SIInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/R600/SIInstrInfo.cpp Fri Sep 26 12:54:52 2014
@@ -1357,8 +1357,27 @@ void SIInstrInfo::legalizeOperands(Machi
   // XXX - Do any VOP3 instructions read VCC?
   // Legalize VOP3
   if (isVOP3(MI->getOpcode())) {
-    int VOP3Idx[3] = {Src0Idx, Src1Idx, Src2Idx};
+    const MCInstrDesc &Desc = get(MI->getOpcode());
     unsigned SGPRReg = AMDGPU::NoRegister;
+
+    int VOP3Idx[3] = { Src0Idx, Src1Idx, Src2Idx };
+
+    // First we need to consider the instruction's operand requirements before
+    // legalizing. Some operands are required to be SGPRs, but we are still
+    // bound by the constant bus requirement to only use one.
+    //
+    // If the operand's class is an SGPR, we can never move it.
+    for (unsigned i = 0; i < 3; ++i) {
+      int Idx = VOP3Idx[i];
+      if (Idx == -1)
+        break;
+
+      if (RI.isSGPRClassID(Desc.OpInfo[Idx].RegClass)) {
+        SGPRReg = MI->getOperand(Idx).getReg();
+        break;
+      }
+    }
+
     for (unsigned i = 0; i < 3; ++i) {
       int Idx = VOP3Idx[i];
       if (Idx == -1)

Modified: llvm/trunk/test/CodeGen/R600/v_cndmask.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/R600/v_cndmask.ll?rev=218529&r1=218528&r2=218529&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/R600/v_cndmask.ll (original)
+++ llvm/trunk/test/CodeGen/R600/v_cndmask.ll Fri Sep 26 12:54:52 2014
@@ -1,14 +1,38 @@
-; RUN: llc < %s -march=r600 -mcpu=SI -verify-machineinstrs | FileCheck --check-prefix=SI %s
+; RUN: llc -march=r600 -mcpu=SI -verify-machineinstrs < %s | FileCheck -check-prefix=SI %s
 
-; SI: @v_cnd_nan
-; SI: V_CNDMASK_B32_e64 v{{[0-9]}},
+declare i32 @llvm.r600.read.tidig.x() #1
+
+; SI-LABEL: @v_cnd_nan_nosgpr
+; SI: V_CNDMASK_B32_e64 v{{[0-9]}}, v{{[0-9]}}, -1, s{{\[[0-9]+:[0-9]+\]}}
 ; SI-DAG: v{{[0-9]}}
 ; All nan values are converted to 0xffffffff
-; SI-DAG: -1
-define void @v_cnd_nan(float addrspace(1)* %out, i32 %c, float %f) {
-entry:
-  %0 = icmp ne i32 %c, 0
-  %1 = select i1 %0, float 0xFFFFFFFFE0000000, float %f
-  store float %1, float addrspace(1)* %out
+; SI: S_ENDPGM
+define void @v_cnd_nan_nosgpr(float addrspace(1)* %out, i32 %c, float addrspace(1)* %fptr) #0 {
+  %idx = call i32 @llvm.r600.read.tidig.x() #1
+  %f.gep = getelementptr float addrspace(1)* %fptr, i32 %idx
+  %f = load float addrspace(1)* %fptr
+  %setcc = icmp ne i32 %c, 0
+  %select = select i1 %setcc, float 0xFFFFFFFFE0000000, float %f
+  store float %select, float addrspace(1)* %out
   ret void
 }
+
+
+; This requires slightly trickier SGPR operand legalization since the
+; single constant bus SGPR usage is the last operand, and it should
+; never be moved.
+
+; SI-LABEL: @v_cnd_nan
+; SI: V_CNDMASK_B32_e64 v{{[0-9]}}, v{{[0-9]}}, -1, s{{\[[0-9]+:[0-9]+\]}}
+; SI-DAG: v{{[0-9]}}
+; All nan values are converted to 0xffffffff
+; SI: S_ENDPGM
+define void @v_cnd_nan(float addrspace(1)* %out, i32 %c, float %f) #0 {
+  %setcc = icmp ne i32 %c, 0
+  %select = select i1 %setcc, float 0xFFFFFFFFE0000000, float %f
+  store float %select, float addrspace(1)* %out
+  ret void
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }





More information about the llvm-commits mailing list