diff options
| author | Eli Friedman <efriedma@codeaurora.org> | 2018-11-07 21:08:13 +0000 |
|---|---|---|
| committer | Eli Friedman <efriedma@codeaurora.org> | 2018-11-07 21:08:13 +0000 |
| commit | 7d7d41debc9abdda7b3710cdabe2bc64e03d5578 (patch) | |
| tree | f30f2999d2cca4812cae6a154fe5d8cf16d33087 /llvm/lib/Target/ARM | |
| parent | 3c5d23912b2a6abe4672679ff2c880d562167e37 (diff) | |
| download | bcm5719-llvm-7d7d41debc9abdda7b3710cdabe2bc64e03d5578.tar.gz bcm5719-llvm-7d7d41debc9abdda7b3710cdabe2bc64e03d5578.zip | |
[ARM] Fix CPSR liveness in tMOVCCr_pseudo lowering.
The lowering was missing live-ins in certain cases, like a sequence of
multiple tMOVCCr_pseudo instructions. This would lead to a verifier
failure, and on pre-v6 Thumb CPSR would be incorrectly clobbered.
For reasons I don't completely understand, it's hard to get a sequence
of multiple tMOVCCr_pseudo instructions; the issue only seems to show up
with 64-bit comparisons where the result is zero-extended. I added some
extra testcases in case that changes in the future. Probably some
optimization opportunities here if anyone is interested. (@test_slt_not
is the case that was getting miscompiled.)
The code to check the liveness of CPSR was stolen from
X86ISelLowering.cpp; maybe it could be refactored into common helper,
but I have no idea where to put it.
Differential Revision: https://reviews.llvm.org/D54192
llvm-svn: 346355
Diffstat (limited to 'llvm/lib/Target/ARM')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 0f68fb0287c..56d2e510cb7 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -9160,6 +9160,42 @@ ARMTargetLowering::EmitLowered__dbzchk(MachineInstr &MI, return ContBB; } +// The CPSR operand of SelectItr might be missing a kill marker +// because there were multiple uses of CPSR, and ISel didn't know +// which to mark. Figure out whether SelectItr should have had a +// kill marker, and set it if it should. Returns the correct kill +// marker value. +static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, + MachineBasicBlock* BB, + const TargetRegisterInfo* TRI) { + // Scan forward through BB for a use/def of CPSR. + MachineBasicBlock::iterator miI(std::next(SelectItr)); + for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) { + const MachineInstr& mi = *miI; + if (mi.readsRegister(ARM::CPSR)) + return false; + if (mi.definesRegister(ARM::CPSR)) + break; // Should have kill-flag - update below. + } + + // If we hit the end of the block, check whether CPSR is live into a + // successor. + if (miI == BB->end()) { + for (MachineBasicBlock::succ_iterator sItr = BB->succ_begin(), + sEnd = BB->succ_end(); + sItr != sEnd; ++sItr) { + MachineBasicBlock* succ = *sItr; + if (succ->isLiveIn(ARM::CPSR)) + return false; + } + } + + // We found a def, or hit the end of the basic block and CPSR wasn't live + // out. SelectMI should have a kill flag on CPSR. + SelectItr->addRegisterKilled(ARM::CPSR, TRI); + return true; +} + MachineBasicBlock * ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { @@ -9259,6 +9295,14 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, F->insert(It, copy0MBB); F->insert(It, sinkMBB); + // Check whether CPSR is live past the tMOVCCr_pseudo. + const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); + if (!MI.killsRegister(ARM::CPSR) && + !checkAndUpdateCPSRKill(MI, thisMBB, TRI)) { + copy0MBB->addLiveIn(ARM::CPSR); + sinkMBB->addLiveIn(ARM::CPSR); + } + // Transfer the remainder of BB and its successor edges to sinkMBB. sinkMBB->splice(sinkMBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), BB->end()); |

