diff options
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64FastISel.cpp')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64FastISel.cpp | 19 | 
1 files changed, 13 insertions, 6 deletions
| diff --git a/llvm/lib/Target/AArch64/AArch64FastISel.cpp b/llvm/lib/Target/AArch64/AArch64FastISel.cpp index 179fe4dd7ff..7ee8c47930a 100644 --- a/llvm/lib/Target/AArch64/AArch64FastISel.cpp +++ b/llvm/lib/Target/AArch64/AArch64FastISel.cpp @@ -2694,8 +2694,11 @@ bool AArch64FastISel::SelectTrunc(const Instruction *I) {    bool SrcIsKill = hasTrivialKill(Op);    // If we're truncating from i64 to a smaller non-legal type then generate an -  // AND.  Otherwise, we know the high bits are undefined and a truncate doesn't -  // generate any code. +  // AND. Otherwise, we know the high bits are undefined and a truncate only +  // generate a COPY. We cannot mark the source register also as result +  // register, because this can incorrectly transfer the kill flag onto the +  // source register. +  unsigned ResultReg;    if (SrcVT == MVT::i64) {      uint64_t Mask = 0;      switch (DestVT.SimpleTy) { @@ -2716,12 +2719,16 @@ bool AArch64FastISel::SelectTrunc(const Instruction *I) {      unsigned Reg32 = FastEmitInst_extractsubreg(MVT::i32, SrcReg, SrcIsKill,                                                  AArch64::sub_32);      // Create the AND instruction which performs the actual truncation. -    unsigned ANDReg = emitAND_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask); -    assert(ANDReg && "Unexpected AND instruction emission failure."); -    SrcReg = ANDReg; +    ResultReg = emitAND_ri(MVT::i32, Reg32, /*IsKill=*/true, Mask); +    assert(ResultReg && "Unexpected AND instruction emission failure."); +  } else { +    ResultReg = createResultReg(&AArch64::GPR32RegClass); +    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, +            TII.get(TargetOpcode::COPY), ResultReg) +        .addReg(SrcReg, getKillRegState(SrcIsKill));    } -  UpdateValueMap(I, SrcReg); +  UpdateValueMap(I, ResultReg);    return true;  } | 

