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 5declare {i16, i32} @llvm.x86.rdrand.16() 6declare {i32, i32} @llvm.x86.rdrand.32() 7 8define 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 34define 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. 59define 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. 82define 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 121entry: 122 %tobool1 = icmp eq i32 %n, 0 123 br i1 %tobool1, label %while.end, label %while.body 124 125while.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 136while.end: ; preds = %while.body, %entry 137 ret void 138} 139