]> granicus.if.org Git - llvm/commitdiff
AMDGPU: Preserve undef flag on vcc when shrinking v_cndmask_b32
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Mon, 20 Jun 2016 18:34:00 +0000 (18:34 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Mon, 20 Jun 2016 18:34:00 +0000 (18:34 +0000)
The implicit operand is added by the initial instruction construction,
so this was adding an additional vcc use. The original one
was missing the undef flag the original condition had,
so the verifier would complain.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273182 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AMDGPU/SIShrinkInstructions.cpp
test/CodeGen/AMDGPU/cndmask-no-def-vcc.ll

index 18ad274d946eed4335043b3b6d4a26869ed956b6..1e13e98f6c77621e0dc1ce66e66b40b7df322830 100644 (file)
@@ -178,18 +178,16 @@ static void foldImmediates(MachineInstr &MI, const SIInstrInfo *TII,
 }
 
 // Copy MachineOperand with all flags except setting it as implicit.
-static MachineOperand copyRegOperandAsImplicit(const MachineOperand &Orig) {
-  assert(!Orig.isImplicit());
-  return MachineOperand::CreateReg(Orig.getReg(),
-                                   Orig.isDef(),
-                                   true,
-                                   Orig.isKill(),
-                                   Orig.isDead(),
-                                   Orig.isUndef(),
-                                   Orig.isEarlyClobber(),
-                                   Orig.getSubReg(),
-                                   Orig.isDebug(),
-                                   Orig.isInternalRead());
+static void copyFlagsToImplicitVCC(MachineInstr &MI,
+                                   const MachineOperand &Orig) {
+
+  for (MachineOperand &Use : MI.implicit_operands()) {
+    if (Use.getReg() == AMDGPU::VCC) {
+      Use.setIsUndef(Orig.isUndef());
+      Use.setIsKill(Orig.isKill());
+      return;
+    }
+  }
 }
 
 static bool isKImmOperand(const SIInstrInfo *TII, const MachineOperand &Src) {
@@ -392,10 +390,9 @@ bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
           Inst32.addOperand(*Src2);
         } else {
           // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
-          // replaced with an implicit read of vcc.
-          assert(Src2->getReg() == AMDGPU::VCC &&
-                 "Unexpected missing register operand");
-          Inst32.addOperand(copyRegOperandAsImplicit(*Src2));
+          // replaced with an implicit read of vcc. This was already added
+          // during the initial BuildMI, so find it to preserve the flags.
+          copyFlagsToImplicitVCC(*Inst32, *Src2);
         }
       }
 
index 28c29a0b77e705d71f2ffa77faf5ac2b8bc6cb73..2c4c07c193af3fe2ce436cf92849b2b19acafc6e 100644 (file)
@@ -1,6 +1,8 @@
 ; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
 
-; Produces error after adding an implicit deff to v_cndmask_b32
+declare i1 @llvm.amdgcn.class.f32(float, i32)
+
+; Produces error after adding an implicit def to v_cndmask_b32
 
 ; GCN-LABEL: {{^}}vcc_shrink_vcc_def:
 ; GCN: v_cmp_eq_i32_e64 vcc, 0, s{{[0-9]+}}
@@ -25,3 +27,30 @@ bb1:
 bb2:
   ret void
 }
+
+; The undef flag on the condition src must be preserved on the
+; implicit vcc use to avoid verifier errors.
+
+; GCN-LABEL: {{^}}preserve_condition_undef_flag:
+; GCN-NOT: vcc
+; GCN: v_cndmask_b32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}}, vcc
+; GCN: v_cndmask_b32_e64 v1, 0, 1, s{{\[[0-9]+:[0-9]+\]}}
+define void @preserve_condition_undef_flag(float %arg, i32 %arg1, float %arg2) {
+bb0:
+  %tmp = icmp sgt i32 %arg1, 4
+  %undef = call i1 @llvm.amdgcn.class.f32(float undef, i32 undef)
+  %tmp4 = select i1 %undef, float %arg, float 1.000000e+00
+  %tmp5 = fcmp ogt float %arg2, 0.000000e+00
+  %tmp6 = fcmp olt float %arg2, 1.000000e+00
+  %tmp7 = fcmp olt float %arg, %tmp4
+  %tmp8 = and i1 %tmp5, %tmp6
+  %tmp9 = and i1 %tmp8, %tmp7
+  br i1 %tmp9, label %bb1, label %bb2
+
+bb1:
+  store volatile i32 0, i32 addrspace(1)* undef
+  br label %bb2
+
+bb2:
+  ret void
+}