From 6100366c2f543ea1bc26b3c22b7543237bd79274 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 16 May 2012 01:54:27 +0000 Subject: [PATCH] Avoid creating a cycle when folding load / op with flag / store. PR11451474. rdar://11451474 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156896 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 14 +++++++++ test/CodeGen/X86/rd-mod-wr-eflags.ll | 46 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 8e2b1d6b5dd..0c7b11625b7 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1905,6 +1905,20 @@ static bool isLoadIncOrDecStore(StoreSDNode *StoreNode, unsigned Opc, ChainCheck = true; continue; } + + // Make sure using Op as part of the chain would not cause a cycle here. + // In theory, we could check whether the chain node is a predecessor of + // the load. But that can be very expensive. Instead visit the uses and + // make sure they all have smaller node id than the load. + int LoadId = LoadNode->getNodeId(); + for (SDNode::use_iterator UI = Op.getNode()->use_begin(), + UE = UI->use_end(); UI != UE; ++UI) { + if (UI.getUse().getResNo() != 0) + continue; + if (UI->getNodeId() > LoadId) + return false; + } + ChainOps.push_back(Op); } diff --git a/test/CodeGen/X86/rd-mod-wr-eflags.ll b/test/CodeGen/X86/rd-mod-wr-eflags.ll index faca3d7bacd..8ef9b5dec0d 100644 --- a/test/CodeGen/X86/rd-mod-wr-eflags.ll +++ b/test/CodeGen/X86/rd-mod-wr-eflags.ll @@ -177,3 +177,49 @@ if.end4: return: ret void } + +; Deal with TokenFactor chain +; rdar://11236106 +@foo = external global i64*, align 8 + +define void @test3() nounwind ssp { +entry: +; CHECK: test3: +; CHECK: decq 16(%rax) + %0 = load i64** @foo, align 8 + %arrayidx = getelementptr inbounds i64* %0, i64 2 + %1 = load i64* %arrayidx, align 8 + %dec = add i64 %1, -1 + store i64 %dec, i64* %arrayidx, align 8 + %cmp = icmp eq i64 %dec, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: + tail call void @baz() nounwind + br label %if.end + +if.end: + ret void +} + +declare void @baz() + +; Avoid creating a cycle in the DAG which would trigger an assert in the +; scheduler. +; PR12565 +; rdar://11451474 +@x = external global i32, align 4 +@y = external global i32, align 4 +@z = external global i32, align 4 + +define void @test4() nounwind uwtable ssp { +entry: + %0 = load i32* @x, align 4 + %1 = load i32* @y, align 4 + %dec = add nsw i32 %1, -1 + store i32 %dec, i32* @y, align 4 + %tobool.i = icmp ne i32 %dec, 0 + %cond.i = select i1 %tobool.i, i32 %0, i32 0 + store i32 %cond.i, i32* @z, align 4 + ret void +} -- 2.34.1