From feae00a68e819e661ff6fddd15be703670247c10 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 12 Jul 2012 18:14:57 +0000 Subject: [PATCH] Give the rdrand instructions a SideEffect flag and a chain so MachineCSE and MachineLICM don't touch it. I already had the necessary things in place for IR-level passes but missed the machine passes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160137 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 6 ++--- lib/Target/X86/X86InstrInfo.td | 3 ++- test/CodeGen/X86/rdrand.ll | 38 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index c242aaa3daf..19cf5bf75a2 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -9823,8 +9823,8 @@ X86TargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const { case Intrinsic::x86_rdrand_32: case Intrinsic::x86_rdrand_64: { // Emit the node with the right value type. - SDValue Result = DAG.getNode(X86ISD::RDRAND, dl, - DAG.getVTList(Op->getValueType(0), MVT::Glue)); + SDVTList VTs = DAG.getVTList(Op->getValueType(0), MVT::Glue, MVT::Other); + SDValue Result = DAG.getNode(X86ISD::RDRAND, dl, VTs, Op.getOperand(0)); // If the value returned by RDRAND was valid (CF=1), return 1. Otherwise // return the value from Rand, which is always 0, casted to i32. @@ -9838,7 +9838,7 @@ X86TargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const { // Return { result, isValid, chain }. return DAG.getNode(ISD::MERGE_VALUES, dl, Op->getVTList(), Result, isValid, - Op.getOperand(0)); + SDValue(Result.getNode(), 2)); } } } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index dc26d4c1dcb..2c4e393556b 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -139,7 +139,8 @@ def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; def X86sahf : SDNode<"X86ISD::SAHF", SDTX86sahf>; -def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand>; +def X86rdrand : SDNode<"X86ISD::RDRAND", SDTX86rdrand, + [SDNPHasChain, SDNPSideEffect]>; def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPMayStore, diff --git a/test/CodeGen/X86/rdrand.ll b/test/CodeGen/X86/rdrand.ll index 78af936a4d3..27d1fe6b275 100644 --- a/test/CodeGen/X86/rdrand.ll +++ b/test/CodeGen/X86/rdrand.ll @@ -45,3 +45,41 @@ define i32 @_rdrand64_step(i64* %random_val) { ; CHECK: cmovael %e[[T1]], %eax ; CHECK: ret } + +; Check that MachineCSE doesn't eliminate duplicate rdrand instructions. +define i32 @CSE() nounwind { + %rand1 = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind + %v1 = extractvalue { i32, i32 } %rand1, 0 + %rand2 = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind + %v2 = extractvalue { i32, i32 } %rand2, 0 + %add = add i32 %v2, %v1 + ret i32 %add +; CHECK: CSE: +; CHECK: rdrandl +; CHECK: rdrandl +} + +; Check that MachineLICM doesn't hoist rdrand instructions. +define void @loop(i32* %p, i32 %n) nounwind { +entry: + %tobool1 = icmp eq i32 %n, 0 + br i1 %tobool1, label %while.end, label %while.body + +while.body: ; preds = %entry, %while.body + %p.addr.03 = phi i32* [ %incdec.ptr, %while.body ], [ %p, %entry ] + %n.addr.02 = phi i32 [ %dec, %while.body ], [ %n, %entry ] + %dec = add nsw i32 %n.addr.02, -1 + %incdec.ptr = getelementptr inbounds i32* %p.addr.03, i64 1 + %rand = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind + %v1 = extractvalue { i32, i32 } %rand, 0 + store i32 %v1, i32* %p.addr.03, align 4 + %tobool = icmp eq i32 %dec, 0 + br i1 %tobool, label %while.end, label %while.body + +while.end: ; preds = %while.body, %entry + ret void +; CHECK: loop: +; CHECK-NOT: rdrandl +; CHECK: This Inner Loop Header: Depth=1 +; CHECK: rdrandl +}