1; RUN: llc -verify-machineinstrs -print-before=peephole-opt -print-after=peephole-opt -mtriple=powerpc64-unknown-linux-gnu -o /dev/null 2>&1 < %s | FileCheck %s 2; RUN: llc -verify-machineinstrs -print-before=peephole-opt -print-after=peephole-opt -mtriple=powerpc64le-unknown-linux-gnu -o /dev/null 2>&1 < %s | FileCheck %s 3 4; CHECK-LABEL: fn1 5define signext i32 @fn1(i32 %baz) { 6 %1 = mul nsw i32 %baz, 208 7 %2 = zext i32 %1 to i64 8 %3 = shl i64 %2, 48 9 %4 = ashr exact i64 %3, 48 10; CHECK: RLWINM8 killed {{[^,]+}}, 0, 16, 27 11; CHECK: CMPLDI 12; CHECK: BCC 13 14; CHECK: ANDI8_rec {{[^,]+}}, 65520, implicit-def $cr0 15; CHECK: COPY killed $cr0 16; CHECK: BCC 17 %5 = icmp eq i64 %4, 0 18 br i1 %5, label %foo, label %bar 19 20foo: 21 ret i32 1 22 23bar: 24 ret i32 0 25} 26 27; CHECK-LABEL: fn2 28define signext i32 @fn2(i64 %a, i64 %b) { 29; CHECK: OR8_rec {{[^, ]+}}, {{[^, ]+}}, implicit-def $cr0 30; CHECK: [[CREG:[^, ]+]]:crrc = COPY killed $cr 31; CHECK: BCC 12, killed [[CREG]] 32 %1 = or i64 %b, %a 33 %2 = icmp sgt i64 %1, -1 34 br i1 %2, label %foo, label %bar 35 36foo: 37 ret i32 1 38 39bar: 40 ret i32 0 41} 42 43; CHECK-LABEL: fn3 44define signext i32 @fn3(i32 %a) { 45; CHECK: ANDI_rec killed {{[%0-9]+}}{{[^,]*}}, 10, implicit-def $cr0 46; CHECK: [[CREG:[^, ]+]]:crrc = COPY $cr0 47; CHECK: BCC 76, killed [[CREG]] 48 %1 = and i32 %a, 10 49 %2 = icmp ne i32 %1, 0 50 br i1 %2, label %foo, label %bar 51 52foo: 53 ret i32 1 54 55bar: 56 ret i32 0 57} 58 59; This test case confirms that a record-form instruction is 60; generated even if the branch has a static branch hint. 61 62; CHECK-LABEL: fn4 63define i64 @fn4(i64 %a, i64 %b) { 64; CHECK: ADD8_rec 65; CHECK-NOT: CMP 66; CHECK: BCC 71 67 68entry: 69 %add = add nsw i64 %b, %a 70 %cmp = icmp eq i64 %add, 0 71 br i1 %cmp, label %if.then, label %if.end 72 73if.then: 74 tail call void @exit(i32 signext 0) #3 75 unreachable 76 77if.end: 78 ret i64 %add 79} 80 81declare void @exit(i32 signext) 82 83; Since %v1 and %v2 are zero-extended 32-bit values, %1 is also zero-extended. 84; In this case, we want to use OR_rec instead of OR + CMPLWI. 85 86; CHECK-LABEL: fn5 87define zeroext i32 @fn5(i32* %p1, i32* %p2) { 88; CHECK: OR_rec 89; CHECK-NOT: CMP 90; CHECK: BCC 91 %v1 = load i32, i32* %p1 92 %v2 = load i32, i32* %p2 93 %1 = or i32 %v1, %v2 94 %2 = icmp eq i32 %1, 0 95 br i1 %2, label %foo, label %bar 96 97foo: 98 ret i32 1 99 100bar: 101 ret i32 0 102} 103 104; This test confirms record-form instructions are emitted for comparison 105; against a non-zero value. 106 107; CHECK-LABEL: fn6 108define i8* @fn6(i8* readonly %p) { 109; CHECK: LBZU 110; CHECK: EXTSB_rec 111; CHECK-NOT: CMP 112; CHECK: BCC 113; CHECK: LBZU 114; CHECK: EXTSB_rec 115; CHECK-NOT: CMP 116; CHECK: BCC 117 118entry: 119 %incdec.ptr = getelementptr inbounds i8, i8* %p, i64 -1 120 %0 = load i8, i8* %incdec.ptr 121 %cmp = icmp sgt i8 %0, -1 122 br i1 %cmp, label %out, label %if.end 123 124if.end: 125 %incdec.ptr2 = getelementptr inbounds i8, i8* %p, i64 -2 126 %1 = load i8, i8* %incdec.ptr2 127 %cmp4 = icmp sgt i8 %1, -1 128 br i1 %cmp4, label %out, label %cleanup 129 130out: 131 %p.addr.0 = phi i8* [ %incdec.ptr, %entry ], [ %incdec.ptr2, %if.end ] 132 br label %cleanup 133 134cleanup: 135 %retval.0 = phi i8* [ %p.addr.0, %out ], [ null, %if.end ] 136 ret i8* %retval.0 137} 138