llvm.org GIT mirror llvm / 1c062c2
Fix -widen-vmovs liveness issues. When widening a copy, we are reading a larger register that may not be live. Use an <undef> flag to tell the register scavenger and machine code verifier that we know the value isn't defined. We now widen: %S6<def> = COPY %S4<kill>, %D3<imp-def> into: %D3<def> = VMOVD %D2<undef>, pred:14, pred:%noreg, %S4<imp-use,kill> This also keeps the <kill> flag on %S4 so we don't inadvertently kill a live value in %S5. Finally, ensure that ARMBaseInstrInfo::setExecutionDomain() preserves the <undef> flag when converting VMOVD to VORR. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141746 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 8 years ago
2 changed file(s) with 65 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
10241024 if (!MI->definesRegister(DstRegD, TRI) || MI->readsRegister(DstRegD, TRI))
10251025 return false;
10261026
1027 // All clear, widen the COPY. Preserve the implicit operands, even if they
1028 // may be superfluous now.
1027 // A dead copy shouldn't show up here, but reject it just in case.
1028 if (MI->getOperand(0).isDead())
1029 return false;
1030
1031 // All clear, widen the COPY.
10291032 DEBUG(dbgs() << "widening: " << *MI);
1033
1034 // Get rid of the old of DstRegD. Leave it if it defines a Q-reg
1035 // or some other super-register.
1036 int ImpDefIdx = MI->findRegisterDefOperandIdx(DstRegD);
1037 if (ImpDefIdx != -1)
1038 MI->RemoveOperand(ImpDefIdx);
1039
1040 // Change the opcode and operands.
10301041 MI->setDesc(get(ARM::VMOVD));
10311042 MI->getOperand(0).setReg(DstRegD);
10321043 MI->getOperand(1).setReg(SrcRegD);
10331044 AddDefaultPred(MachineInstrBuilder(MI));
1045
1046 // We are now reading SrcRegD instead of SrcRegS. This may upset the
1047 // register scavenger and machine verifier, so we need to indicate that we
1048 // are reading an undefined value from SrcRegD, but a proper value from
1049 // SrcRegS.
1050 MI->getOperand(1).setIsUndef();
1051 MachineInstrBuilder(MI).addReg(SrcRegS, RegState::Implicit);
1052
1053 // SrcRegD may actually contain an unrelated value in the ssub_1
1054 // sub-register. Don't kill it. Only kill the ssub_0 sub-register.
1055 if (MI->getOperand(1).isKill()) {
1056 MI->getOperand(1).setIsKill(false);
1057 MI->addRegisterKilled(SrcRegS, TRI, true);
1058 }
1059
10341060 DEBUG(dbgs() << "replaced by: " << *MI);
10351061 return true;
10361062 }
27992825
28002826 // Add the extra source operand and new predicates.
28012827 // This will go before any implicit ops.
2802 AddDefaultPred(MachineInstrBuilder(MI).addReg(MI->getOperand(1).getReg()));
2803 }
2828 AddDefaultPred(MachineInstrBuilder(MI).addOperand(MI->getOperand(1)));
2829 }
0 ; RUN: llc < %s -widen-vmovs -mcpu=cortex-a8 -verify-machineinstrs | FileCheck %s
1 target triple = "thumbv7-apple-ios"
2
3 ; The 0.0 constant is loaded from the constant pool and kept in a register.
4 ; CHECK: %entry
5 ; CHECK: vldr.32 s
6 ; The float loop variable is initialized with a vmovs from the constant register.
7 ; The vmovs is first widened to a vmovd, and then converted to a vorr because of the v2f32 vadd.f32.
8 ; CHECK: vorr [[DL:d[0-9]+]], [[DN:d[0-9]+]]
9 ; CHECK: , [[DN]]
10 ; CHECK: %for.body.i
11 ; CHECK: vadd.f32 [[DL]], [[DL]], [[DN]]
12 ;
13 ; This test is verifying:
14 ; - The VMOVS widening is happening.
15 ; - Register liveness is verified.
16 ; - The execution domain switch to vorr works across basic blocks.
17
18 define void @Mm() nounwind {
19 entry:
20 br label %for.body4
21
22 for.body4:
23 br label %for.body.i
24
25 for.body.i:
26 %tmp3.i = phi float [ 0.000000e+00, %for.body4 ], [ %add.i, %for.body.i ]
27 %add.i = fadd float %tmp3.i, 0.000000e+00
28 %exitcond.i = icmp eq i32 undef, 41
29 br i1 %exitcond.i, label %rInnerproduct.exit, label %for.body.i
30
31 rInnerproduct.exit:
32 store float %add.i, float* undef, align 4
33 br label %for.body4
34 }