AMDGPU: Preserve undef flag on vcc when shrinking v_cndmask_b32

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
This commit is contained in:
Matt Arsenault 2016-06-20 18:34:00 +00:00
parent 17f22f98eb
commit b2902b2eb0
2 changed files with 43 additions and 17 deletions

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

View 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
}