// 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)
-; 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 }