}
break;
}
+ case ISD::STORE: {
+ StoreSDNode *StoreNode = cast<StoreSDNode>(Node);
+ SDValue Chain = StoreNode->getOperand(0);
+ SDValue StoredVal = StoreNode->getOperand(1);
+ SDValue Address = StoreNode->getOperand(2);
+ SDValue Undef = StoreNode->getOperand(3);
+
+ if (StoreNode->getMemOperand()->getSize() != 8 ||
+ Undef->getOpcode() != ISD::UNDEF ||
+ Chain->getOpcode() != ISD::LOAD ||
+ StoredVal->getOpcode() != X86ISD::DEC ||
+ StoredVal.getResNo() != 0 ||
+ StoredVal->getOperand(0).getNode() != Chain.getNode())
+ break;
+
+ //OPC_CheckPredicate, 1, // Predicate_nontemporalstore
+ if (StoreNode->isNonTemporal())
+ break;
+
+ LoadSDNode *LoadNode = cast<LoadSDNode>(Chain.getNode());
+ if (LoadNode->getOperand(1) != Address ||
+ LoadNode->getOperand(2) != Undef)
+ break;
+
+ if (!ISD::isNormalLoad(LoadNode))
+ break;
+
+ if (!ISD::isNormalStore(StoreNode))
+ break;
+
+ // check load chain has only one use (from the store)
+ if (!Chain.hasOneUse())
+ break;
+
+ // Merge the input chains if they are not intra-pattern references.
+ SDValue InputChain = LoadNode->getOperand(0);
+
+ SDValue Base, Scale, Index, Disp, Segment;
+ if (!SelectAddr(LoadNode, LoadNode->getBasePtr(),
+ Base, Scale, Index, Disp, Segment))
+ break;
+
+ MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(2);
+ MemOp[0] = StoreNode->getMemOperand();
+ MemOp[1] = LoadNode->getMemOperand();
+ const SDValue Ops[] = { Base, Scale, Index, Disp, Segment, InputChain };
+ MachineSDNode *Result = CurDAG->getMachineNode(X86::DEC64m,
+ Node->getDebugLoc(),
+ MVT::i32, MVT::Other, Ops,
+ array_lengthof(Ops));
+ Result->setMemRefs(MemOp, MemOp + 2);
+
+ ReplaceUses(SDValue(StoreNode, 0), SDValue(Result, 1));
+ ReplaceUses(SDValue(StoredVal.getNode(), 1), SDValue(Result, 0));
+
+ return Result;
+ }
}
SDNode *ResNode = SelectCode(Node);
// climbing the DAG back to the root, and it doesn't seem to be worth the
// effort.
for (SDNode::use_iterator UI = Op.getNode()->use_begin(),
- UE = Op.getNode()->use_end(); UI != UE; ++UI)
- if (UI->getOpcode() != ISD::CopyToReg && UI->getOpcode() != ISD::SETCC)
+ UE = Op.getNode()->use_end(); UI != UE; ++UI)
+ if (UI->getOpcode() != ISD::CopyToReg &&
+ UI->getOpcode() != ISD::SETCC &&
+ UI->getOpcode() != ISD::STORE)
goto default_case;
if (ConstantSDNode *C =
--- /dev/null
+; RUN: llc < %s -march=x86-64 | FileCheck %s
+
+%struct.obj = type { i64 }
+
+define void @_Z7releaseP3obj(%struct.obj* nocapture %o) nounwind uwtable ssp {
+entry:
+; CHECK: decq (%rdi)
+; CHECK-NEXT: je
+ %refcnt = getelementptr inbounds %struct.obj* %o, i64 0, i32 0
+ %0 = load i64* %refcnt, align 8, !tbaa !0
+ %dec = add i64 %0, -1
+ store i64 %dec, i64* %refcnt, align 8, !tbaa !0
+ %tobool = icmp eq i64 %dec, 0
+ br i1 %tobool, label %if.end, label %return
+
+if.end: ; preds = %entry
+ %1 = bitcast %struct.obj* %o to i8*
+ tail call void @free(i8* %1)
+ br label %return
+
+return: ; preds = %entry, %if.end
+ ret void
+}
+
+declare void @free(i8* nocapture) nounwind
+
+!0 = metadata !{metadata !"long", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA", null}