diff options
Diffstat (limited to 'devel/llvm60/files/patch-head-r337615.diff')
-rw-r--r-- | devel/llvm60/files/patch-head-r337615.diff | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/devel/llvm60/files/patch-head-r337615.diff b/devel/llvm60/files/patch-head-r337615.diff new file mode 100644 index 000000000000..645240b71cf3 --- /dev/null +++ b/devel/llvm60/files/patch-head-r337615.diff @@ -0,0 +1,64 @@ +r337615 | dim | 2018-08-11 12:42:12 +0200 (Sat, 11 Aug 2018) | 43 lines + +Pull in r338481 from upstream llvm trunk (by Chandler Carruth): + + [x86] Fix a really subtle miscompile due to a somewhat glaring bug in + EFLAGS copy lowering. + + If you have a branch of LLVM, you may want to cherrypick this. It is + extremely unlikely to hit this case empirically, but it will likely + manifest as an "impossible" branch being taken somewhere, and will be + ... very hard to debug. + + Hitting this requires complex conditions living across complex + control flow combined with some interesting memory (non-stack) + initialized with the results of a comparison. Also, because you have + to arrange for an EFLAGS copy to be in *just* the right place, almost + anything you do to the code will hide the bug. I was unable to reduce + anything remotely resembling a "good" test case from the place where + I hit it, and so instead I have constructed synthetic MIR testing + that directly exercises the bug in question (as well as the good + behavior for completeness). + + The issue is that we would mistakenly assume any SETcc with a valid + condition and an initial operand that was a register and a virtual + register at that to be a register *defining* SETcc... + + It isn't though.... + + This would in turn cause us to test some other bizarre register, + typically the base pointer of some memory. Now, testing this register + and using that to branch on doesn't make any sense. It even fails the + machine verifier (if you are running it) due to the wrong register + class. But it will make it through LLVM, assemble, and it *looks* + fine... But wow do you get a very unsual and surprising branch taken + in your actual code. + + The fix is to actually check what kind of SETcc instruction we're + dealing with. Because there are a bunch of them, I just test the + may-store bit in the instruction. I've also added an assert for + sanity that ensure we are, in fact, *defining* the register operand. + =D + +Noticed by: kib +MFC after: 1 week + +Index: lib/Target/X86/X86FlagsCopyLowering.cpp +=================================================================== +--- lib/Target/X86/X86FlagsCopyLowering.cpp (revision 337614) ++++ lib/Target/X86/X86FlagsCopyLowering.cpp (revision 337615) +@@ -608,9 +608,12 @@ X86FlagsCopyLoweringPass::collectCondsInRegs(Machi + for (MachineInstr &MI : llvm::reverse( + llvm::make_range(MBB.instr_begin(), CopyDefI.getIterator()))) { + X86::CondCode Cond = X86::getCondFromSETOpc(MI.getOpcode()); +- if (Cond != X86::COND_INVALID && MI.getOperand(0).isReg() && +- TRI->isVirtualRegister(MI.getOperand(0).getReg())) ++ if (Cond != X86::COND_INVALID && !MI.mayStore() && MI.getOperand(0).isReg() && ++ TRI->isVirtualRegister(MI.getOperand(0).getReg())) { ++ assert(MI.getOperand(0).isDef() && ++ "A non-storing SETcc should always define a register!"); + CondRegs[Cond] = MI.getOperand(0).getReg(); ++ } + + // Stop scanning when we see the first definition of the EFLAGS as prior to + // this we would potentially capture the wrong flag state. |