1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s 3 4; This test checks the isomorphic comparisons can be outlined together into one 5; function. 6 7; The following three function are identical, except that in the third, the 8; operand order, and predicate are swapped, meaning it is structurally the same 9; and should be outlined together. 10 11define void @outline_slt1() { 12; CHECK-LABEL: @outline_slt1( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 15; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 16; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]]) 17; CHECK-NEXT: ret void 18; 19entry: 20 %a = alloca i32, align 4 21 %b = alloca i32, align 4 22 store i32 2, ptr %a, align 4 23 store i32 3, ptr %b, align 4 24 %al = load i32, ptr %a 25 %bl = load i32, ptr %b 26 %0 = icmp slt i32 %al, %bl 27 ret void 28} 29 30define void @outline_slt2() { 31; CHECK-LABEL: @outline_slt2( 32; CHECK-NEXT: entry: 33; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 34; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 35; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]]) 36; CHECK-NEXT: ret void 37; 38entry: 39 %a = alloca i32, align 4 40 %b = alloca i32, align 4 41 store i32 2, ptr %a, align 4 42 store i32 3, ptr %b, align 4 43 %al = load i32, ptr %a 44 %bl = load i32, ptr %b 45 %0 = icmp slt i32 %al, %bl 46 ret void 47} 48 49define void @outline_sgt() { 50; CHECK-LABEL: @outline_sgt( 51; CHECK-NEXT: entry: 52; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 53; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 54; CHECK-NEXT: call void @outlined_ir_func_1(ptr [[A]], ptr [[B]]) 55; CHECK-NEXT: ret void 56; 57entry: 58 %a = alloca i32, align 4 59 %b = alloca i32, align 4 60 store i32 2, ptr %a, align 4 61 store i32 3, ptr %b, align 4 62 %al = load i32, ptr %a 63 %bl = load i32, ptr %b 64 %0 = icmp sgt i32 %bl, %al 65 ret void 66} 67 68; This has a swapped predicate, but not swapped operands, so it cannot use 69; the same outlined function as the ones above. 70 71define void @dontoutline_sgt() { 72; CHECK-LABEL: @dontoutline_sgt( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 75; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 76; CHECK-NEXT: store i32 2, ptr [[A]], align 4 77; CHECK-NEXT: store i32 3, ptr [[B]], align 4 78; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[A]], align 4 79; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[B]], align 4 80; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[AL]], [[BL]] 81; CHECK-NEXT: ret void 82; 83entry: 84 %a = alloca i32, align 4 85 %b = alloca i32, align 4 86 store i32 2, ptr %a, align 4 87 store i32 3, ptr %b, align 4 88 %al = load i32, ptr %a 89 %bl = load i32, ptr %b 90 %0 = icmp sgt i32 %al, %bl 91 ret void 92} 93 94; The below functions use a different kind of predicate that is not compatible 95; with the ones above, and should use a different outlined function. 96; The other difference here is that the predicate with swapped operands comes 97; first this time. 98 99define void @outline_ugt1() { 100; CHECK-LABEL: @outline_ugt1( 101; CHECK-NEXT: entry: 102; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 103; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 104; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 105; CHECK-NEXT: ret void 106; 107entry: 108 %a = alloca i32, align 4 109 %b = alloca i32, align 4 110 store i32 2, ptr %a, align 4 111 store i32 3, ptr %b, align 4 112 %al = load i32, ptr %a 113 %bl = load i32, ptr %b 114 %0 = icmp ugt i32 %al, %bl 115 ret void 116} 117 118define void @outline_ugt2() { 119; CHECK-LABEL: @outline_ugt2( 120; CHECK-NEXT: entry: 121; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 122; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 123; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 124; CHECK-NEXT: ret void 125; 126entry: 127 %a = alloca i32, align 4 128 %b = alloca i32, align 4 129 store i32 2, ptr %a, align 4 130 store i32 3, ptr %b, align 4 131 %al = load i32, ptr %a 132 %bl = load i32, ptr %b 133 %0 = icmp ugt i32 %al, %bl 134 ret void 135} 136 137define void @outline_ult() { 138; CHECK-LABEL: @outline_ult( 139; CHECK-NEXT: entry: 140; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 141; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 142; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[A]], ptr [[B]]) 143; CHECK-NEXT: ret void 144; 145entry: 146 %a = alloca i32, align 4 147 %b = alloca i32, align 4 148 store i32 2, ptr %a, align 4 149 store i32 3, ptr %b, align 4 150 %al = load i32, ptr %a 151 %bl = load i32, ptr %b 152 %0 = icmp ult i32 %bl, %al 153 ret void 154} 155 156; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 { 157; CHECK: entry_to_outline: 158; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4 159; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4 160; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4 161; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4 162; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[AL]], [[BL]] 163 164; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 { 165; CHECK: entry_to_outline: 166; CHECK-NEXT: store i32 2, ptr [[ARG0]], align 4 167; CHECK-NEXT: store i32 3, ptr [[ARG1]], align 4 168; CHECK-NEXT: [[AL:%.*]] = load i32, ptr [[ARG0]], align 4 169; CHECK-NEXT: [[BL:%.*]] = load i32, ptr [[ARG1]], align 4 170; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[AL]], [[BL]] 171