1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4define i1 @bitcast_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) { 5; CHECK-LABEL: @bitcast_and_cmp( 6; CHECK-NEXT: check.0.min: 7; CHECK-NEXT: [[SRC_C:%.*]] = bitcast i32* [[SRC:%.*]] to i8* 8; CHECK-NEXT: [[MIN_C:%.*]] = bitcast i32* [[MIN:%.*]] to i8* 9; CHECK-NEXT: [[MAX_C:%.*]] = bitcast i32* [[MAX:%.*]] to i16* 10; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3 11; CHECK-NEXT: [[GEP_3_C:%.*]] = bitcast i32* [[GEP_3]] to i16* 12; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult i8* [[SRC_C]], [[MIN_C]] 13; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ugt i16* [[GEP_3_C]], [[MAX_C]] 14; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]] 15; CHECK-NEXT: br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]] 16; CHECK: trap: 17; CHECK-NEXT: ret i1 false 18; CHECK: checks: 19; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]] 20; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]] 21; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, [[C_3_MAX]] 22; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1 23; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]] 24; CHECK-NEXT: [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]] 25; CHECK-NEXT: [[RES_2:%.*]] = xor i1 false, true 26; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2 27; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]] 28; CHECK-NEXT: [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]] 29; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true 30; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4 31; CHECK-NEXT: [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]] 32; CHECK-NEXT: [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]] 33; CHECK-NEXT: [[RES_4:%.*]] = xor i1 false, [[C_4_MAX]] 34; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]] 35; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]] 36; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]] 37; CHECK-NEXT: ret i1 [[RES_7]] 38; 39check.0.min: 40 %src.c = bitcast i32* %src to i8* 41 %min.c = bitcast i32* %min to i8* 42 %max.c = bitcast i32* %max to i16* 43 44 %gep.3 = getelementptr inbounds i32, i32* %src, i64 3 45 %gep.3.c = bitcast i32* %gep.3 to i16* 46 %c.min.0 = icmp ult i8* %src.c, %min.c 47 %c.max.3 = icmp ugt i16* %gep.3.c, %max.c 48 49 %or = or i1 %c.min.0, %c.max.3 50 br i1 %or, label %trap, label %checks 51 52trap: 53 ret i1 0 54 55checks: 56 %c.3.min = icmp ult i32* %gep.3, %min 57 %c.3.max = icmp ult i32* %gep.3, %max 58 %res.1 = xor i1 %c.3.min, %c.3.max 59 60 %gep.1 = getelementptr inbounds i32, i32* %src, i64 1 61 %c.1.min = icmp ult i32* %gep.1, %min 62 %c.1.max = icmp ult i32* %gep.1, %max 63 %res.2 = xor i1 %c.1.min, %c.1.max 64 65 %gep.2 = getelementptr inbounds i32, i32* %src, i64 2 66 %c.2.min = icmp ult i32* %gep.2, %min 67 %c.2.max = icmp ult i32* %gep.2, %max 68 %res.3 = xor i1 %c.2.min, %c.2.max 69 70 %gep.4 = getelementptr inbounds i32, i32* %src, i64 4 71 %c.4.min = icmp ult i32* %gep.4, %min 72 %c.4.max = icmp ult i32* %gep.4, %max 73 %res.4 = xor i1 %c.4.min, %c.4.max 74 75 %res.5 = xor i1 %res.1, %res.2 76 %res.6 = xor i1 %res.5, %res.3 77 %res.7 = xor i1 %res.6, %res.4 78 79 ret i1 %res.7 80} 81 82define i1 @gep0_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) { 83; CHECK-LABEL: @gep0_and_cmp( 84; CHECK-NEXT: check.0.min: 85; CHECK-NEXT: [[SRC_C:%.*]] = getelementptr i32, i32* [[SRC:%.*]], i64 0 86; CHECK-NEXT: [[MIN_C:%.*]] = getelementptr i32, i32* [[MIN:%.*]], i64 0 87; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3 88; CHECK-NEXT: [[GEP_3_C:%.*]] = getelementptr i32, i32* [[GEP_3]], i32 0 89; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult i32* [[SRC_C]], [[MIN_C]] 90; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ugt i32* [[GEP_3_C]], [[MAX:%.*]] 91; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]] 92; CHECK-NEXT: br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]] 93; CHECK: trap: 94; CHECK-NEXT: ret i1 false 95; CHECK: checks: 96; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]] 97; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]] 98; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, [[C_3_MAX]] 99; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1 100; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]] 101; CHECK-NEXT: [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]] 102; CHECK-NEXT: [[RES_2:%.*]] = xor i1 false, true 103; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2 104; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]] 105; CHECK-NEXT: [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]] 106; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true 107; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4 108; CHECK-NEXT: [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]] 109; CHECK-NEXT: [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]] 110; CHECK-NEXT: [[RES_4:%.*]] = xor i1 false, [[C_4_MAX]] 111; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]] 112; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]] 113; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]] 114; CHECK-NEXT: ret i1 [[RES_7]] 115; 116check.0.min: 117 %src.c = getelementptr i32, i32* %src, i64 0 118 %min.c = getelementptr i32, i32* %min, i64 0 119 120 %gep.3 = getelementptr inbounds i32, i32* %src, i64 3 121 %gep.3.c = getelementptr i32, i32* %gep.3, i32 0 122 %c.min.0 = icmp ult i32* %src.c, %min.c 123 %c.max.3 = icmp ugt i32* %gep.3.c, %max 124 125 %or = or i1 %c.min.0, %c.max.3 126 br i1 %or, label %trap, label %checks 127 128trap: 129 ret i1 0 130 131checks: 132 %c.3.min = icmp ult i32* %gep.3, %min 133 %c.3.max = icmp ult i32* %gep.3, %max 134 %res.1 = xor i1 %c.3.min, %c.3.max 135 136 %gep.1 = getelementptr inbounds i32, i32* %src, i64 1 137 %c.1.min = icmp ult i32* %gep.1, %min 138 %c.1.max = icmp ult i32* %gep.1, %max 139 %res.2 = xor i1 %c.1.min, %c.1.max 140 141 %gep.2 = getelementptr inbounds i32, i32* %src, i64 2 142 %c.2.min = icmp ult i32* %gep.2, %min 143 %c.2.max = icmp ult i32* %gep.2, %max 144 %res.3 = xor i1 %c.2.min, %c.2.max 145 146 %gep.4 = getelementptr inbounds i32, i32* %src, i64 4 147 %c.4.min = icmp ult i32* %gep.4, %min 148 %c.4.max = icmp ult i32* %gep.4, %max 149 %res.4 = xor i1 %c.4.min, %c.4.max 150 151 %res.5 = xor i1 %res.1, %res.2 152 %res.6 = xor i1 %res.5, %res.3 153 %res.7 = xor i1 %res.6, %res.4 154 155 ret i1 %res.7 156} 157 158; Should not look through addresspacecast, because it may change the pointer 159; value. 160define i1 @addrspacecast_and_cmp(i32* readonly %src, i32* readnone %min, i32* readnone %max) { 161; CHECK-LABEL: @addrspacecast_and_cmp( 162; CHECK-NEXT: check.0.min: 163; CHECK-NEXT: [[SRC_C:%.*]] = addrspacecast i32* [[SRC:%.*]] to i8 addrspace(1)* 164; CHECK-NEXT: [[MIN_C:%.*]] = addrspacecast i32* [[MIN:%.*]] to i8 addrspace(1)* 165; CHECK-NEXT: [[MAX_C:%.*]] = addrspacecast i32* [[MAX:%.*]] to i16 addrspace(1)* 166; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 3 167; CHECK-NEXT: [[GEP_3_C:%.*]] = addrspacecast i32* [[GEP_3]] to i16 addrspace(1)* 168; CHECK-NEXT: [[C_MIN_0:%.*]] = icmp ult i8 addrspace(1)* [[SRC_C]], [[MIN_C]] 169; CHECK-NEXT: [[C_MAX_3:%.*]] = icmp ugt i16 addrspace(1)* [[GEP_3_C]], [[MAX_C]] 170; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_MIN_0]], [[C_MAX_3]] 171; CHECK-NEXT: br i1 [[OR]], label [[TRAP:%.*]], label [[CHECKS:%.*]] 172; CHECK: trap: 173; CHECK-NEXT: ret i1 false 174; CHECK: checks: 175; CHECK-NEXT: [[C_3_MIN:%.*]] = icmp ult i32* [[GEP_3]], [[MIN]] 176; CHECK-NEXT: [[C_3_MAX:%.*]] = icmp ult i32* [[GEP_3]], [[MAX]] 177; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_3_MIN]], [[C_3_MAX]] 178; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 1 179; CHECK-NEXT: [[C_1_MIN:%.*]] = icmp ult i32* [[GEP_1]], [[MIN]] 180; CHECK-NEXT: [[C_1_MAX:%.*]] = icmp ult i32* [[GEP_1]], [[MAX]] 181; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[C_1_MIN]], [[C_1_MAX]] 182; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 2 183; CHECK-NEXT: [[C_2_MIN:%.*]] = icmp ult i32* [[GEP_2]], [[MIN]] 184; CHECK-NEXT: [[C_2_MAX:%.*]] = icmp ult i32* [[GEP_2]], [[MAX]] 185; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[C_2_MIN]], [[C_2_MAX]] 186; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr inbounds i32, i32* [[SRC]], i64 4 187; CHECK-NEXT: [[C_4_MIN:%.*]] = icmp ult i32* [[GEP_4]], [[MIN]] 188; CHECK-NEXT: [[C_4_MAX:%.*]] = icmp ult i32* [[GEP_4]], [[MAX]] 189; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[C_4_MIN]], [[C_4_MAX]] 190; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_1]], [[RES_2]] 191; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[RES_3]] 192; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[RES_4]] 193; CHECK-NEXT: ret i1 [[RES_7]] 194; 195check.0.min: 196 %src.c = addrspacecast i32* %src to i8 addrspace(1)* 197 %min.c = addrspacecast i32* %min to i8 addrspace(1)* 198 %max.c = addrspacecast i32* %max to i16 addrspace(1)* 199 200 %gep.3 = getelementptr inbounds i32, i32* %src, i64 3 201 %gep.3.c = addrspacecast i32* %gep.3 to i16 addrspace(1) * 202 %c.min.0 = icmp ult i8 addrspace(1)* %src.c, %min.c 203 %c.max.3 = icmp ugt i16 addrspace(1)* %gep.3.c, %max.c 204 205 %or = or i1 %c.min.0, %c.max.3 206 br i1 %or, label %trap, label %checks 207 208trap: 209 ret i1 0 210 211checks: 212 %c.3.min = icmp ult i32* %gep.3, %min 213 %c.3.max = icmp ult i32* %gep.3, %max 214 %res.1 = xor i1 %c.3.min, %c.3.max 215 216 %gep.1 = getelementptr inbounds i32, i32* %src, i64 1 217 %c.1.min = icmp ult i32* %gep.1, %min 218 %c.1.max = icmp ult i32* %gep.1, %max 219 %res.2 = xor i1 %c.1.min, %c.1.max 220 221 %gep.2 = getelementptr inbounds i32, i32* %src, i64 2 222 %c.2.min = icmp ult i32* %gep.2, %min 223 %c.2.max = icmp ult i32* %gep.2, %max 224 %res.3 = xor i1 %c.2.min, %c.2.max 225 226 %gep.4 = getelementptr inbounds i32, i32* %src, i64 4 227 %c.4.min = icmp ult i32* %gep.4, %min 228 %c.4.max = icmp ult i32* %gep.4, %max 229 %res.4 = xor i1 %c.4.min, %c.4.max 230 231 %res.5 = xor i1 %res.1, %res.2 232 %res.6 = xor i1 %res.5, %res.3 233 %res.7 = xor i1 %res.6, %res.4 234 235 ret i1 %res.7 236} 237