1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mtriple=i686-unknown-unknown -mcpu=core-avx-i -mattr=+rdrnd | FileCheck %s --check-prefix=X86 3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=core-avx-i -mattr=+rdrnd | FileCheck %s --check-prefix=X64 4 5 declare {i16, i32} @llvm.x86.rdrand.16() 6 declare {i32, i32} @llvm.x86.rdrand.32() 7 8 define i32 @_rdrand16_step(i16* %random_val) { 9 ; X86-LABEL: _rdrand16_step: 10 ; X86: # %bb.0: 11 ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 12 ; X86-NEXT: rdrandw %ax 13 ; X86-NEXT: movzwl %ax, %edx 14 ; X86-NEXT: movl $1, %eax 15 ; X86-NEXT: cmovael %edx, %eax 16 ; X86-NEXT: movw %dx, (%ecx) 17 ; X86-NEXT: retl 18 ; 19 ; X64-LABEL: _rdrand16_step: 20 ; X64: # %bb.0: 21 ; X64-NEXT: rdrandw %ax 22 ; X64-NEXT: movzwl %ax, %ecx 23 ; X64-NEXT: movl $1, %eax 24 ; X64-NEXT: cmovael %ecx, %eax 25 ; X64-NEXT: movw %cx, (%rdi) 26 ; X64-NEXT: retq 27 %call = call {i16, i32} @llvm.x86.rdrand.16() 28 %randval = extractvalue {i16, i32} %call, 0 29 store i16 %randval, i16* %random_val 30 %isvalid = extractvalue {i16, i32} %call, 1 31 ret i32 %isvalid 32 } 33 34 define i32 @_rdrand32_step(i32* %random_val) { 35 ; X86-LABEL: _rdrand32_step: 36 ; X86: # %bb.0: 37 ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 38 ; X86-NEXT: rdrandl %edx 39 ; X86-NEXT: movl $1, %eax 40 ; X86-NEXT: cmovael %edx, %eax 41 ; X86-NEXT: movl %edx, (%ecx) 42 ; X86-NEXT: retl 43 ; 44 ; X64-LABEL: _rdrand32_step: 45 ; X64: # %bb.0: 46 ; X64-NEXT: rdrandl %ecx 47 ; X64-NEXT: movl $1, %eax 48 ; X64-NEXT: cmovael %ecx, %eax 49 ; X64-NEXT: movl %ecx, (%rdi) 50 ; X64-NEXT: retq 51 %call = call {i32, i32} @llvm.x86.rdrand.32() 52 %randval = extractvalue {i32, i32} %call, 0 53 store i32 %randval, i32* %random_val 54 %isvalid = extractvalue {i32, i32} %call, 1 55 ret i32 %isvalid 56 } 57 58 ; Check that MachineCSE doesn't eliminate duplicate rdrand instructions. 59 define i32 @CSE() nounwind { 60 ; X86-LABEL: CSE: 61 ; X86: # %bb.0: 62 ; X86-NEXT: rdrandl %ecx 63 ; X86-NEXT: rdrandl %eax 64 ; X86-NEXT: addl %ecx, %eax 65 ; X86-NEXT: retl 66 ; 67 ; X64-LABEL: CSE: 68 ; X64: # %bb.0: 69 ; X64-NEXT: rdrandl %ecx 70 ; X64-NEXT: rdrandl %eax 71 ; X64-NEXT: addl %ecx, %eax 72 ; X64-NEXT: retq 73 %rand1 = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind 74 %v1 = extractvalue { i32, i32 } %rand1, 0 75 %rand2 = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind 76 %v2 = extractvalue { i32, i32 } %rand2, 0 77 %add = add i32 %v2, %v1 78 ret i32 %add 79 } 80 81 ; Check that MachineLICM doesn't hoist rdrand instructions. 82 define void @loop(i32* %p, i32 %n) nounwind { 83 ; X86-LABEL: loop: 84 ; X86: # %bb.0: # %entry 85 ; X86-NEXT: pushl %esi 86 ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax 87 ; X86-NEXT: testl %eax, %eax 88 ; X86-NEXT: je .LBB3_3 89 ; X86-NEXT: # %bb.1: # %while.body.preheader 90 ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx 91 ; X86-NEXT: xorl %edx, %edx 92 ; X86-NEXT: .p2align 4, 0x90 93 ; X86-NEXT: .LBB3_2: # %while.body 94 ; X86-NEXT: # =>This Inner Loop Header: Depth=1 95 ; X86-NEXT: rdrandl %esi 96 ; X86-NEXT: movl %esi, (%ecx,%edx,4) 97 ; X86-NEXT: addl $1, %edx 98 ; X86-NEXT: cmpl %edx, %eax 99 ; X86-NEXT: jne .LBB3_2 100 ; X86-NEXT: .LBB3_3: # %while.end 101 ; X86-NEXT: popl %esi 102 ; X86-NEXT: retl 103 ; 104 ; X64-LABEL: loop: 105 ; X64: # %bb.0: # %entry 106 ; X64-NEXT: testl %esi, %esi 107 ; X64-NEXT: je .LBB3_3 108 ; X64-NEXT: # %bb.1: # %while.body.preheader 109 ; X64-NEXT: movl %esi, %eax 110 ; X64-NEXT: xorl %ecx, %ecx 111 ; X64-NEXT: .p2align 4, 0x90 112 ; X64-NEXT: .LBB3_2: # %while.body 113 ; X64-NEXT: # =>This Inner Loop Header: Depth=1 114 ; X64-NEXT: rdrandl %edx 115 ; X64-NEXT: movl %edx, (%rdi,%rcx,4) 116 ; X64-NEXT: addq $1, %rcx 117 ; X64-NEXT: cmpl %ecx, %eax 118 ; X64-NEXT: jne .LBB3_2 119 ; X64-NEXT: .LBB3_3: # %while.end 120 ; X64-NEXT: retq 121 entry: 122 %tobool1 = icmp eq i32 %n, 0 123 br i1 %tobool1, label %while.end, label %while.body 124 125 while.body: ; preds = %entry, %while.body 126 %p.addr.03 = phi i32* [ %incdec.ptr, %while.body ], [ %p, %entry ] 127 %n.addr.02 = phi i32 [ %dec, %while.body ], [ %n, %entry ] 128 %dec = add nsw i32 %n.addr.02, -1 129 %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.03, i64 1 130 %rand = tail call { i32, i32 } @llvm.x86.rdrand.32() nounwind 131 %v1 = extractvalue { i32, i32 } %rand, 0 132 store i32 %v1, i32* %p.addr.03, align 4 133 %tobool = icmp eq i32 %dec, 0 134 br i1 %tobool, label %while.end, label %while.body 135 136 while.end: ; preds = %while.body, %entry 137 ret void 138 } 139