296 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4declare void @use(i8)5 6define i1 @test1(i32 %i, ptr %p) {7; CHECK-LABEL: define i1 @test1(8; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {9; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 3110; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 111; CHECK-NEXT: ret i1 false12;13 %lobit = lshr i32 %i, 3114 %t = trunc nuw i32 %lobit to i115 %b = icmp slt i32 %i, 016 %not = xor i1 %t, true17 %op = select i1 %not, i1 %b, i1 false18 store i32 %lobit, ptr %p, align 119 ret i1 %op20}21 22define i1 @test2(i32 %i, ptr %p) {23; CHECK-LABEL: define i1 @test2(24; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {25; CHECK-NEXT: [[DOTLOBIT:%.*]] = ashr i32 [[I]], 3126; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 127; CHECK-NEXT: ret i1 false28;29 %lobit = ashr i32 %i, 3130 %t = trunc nuw i32 %lobit to i131 %b = icmp slt i32 %i, 032 %not = xor i1 %t, true33 %op = select i1 %not, i1 %b, i1 false34 store i32 %lobit, ptr %p, align 135 ret i1 %op36}37 38define i1 @test3(i32 %i, ptr %p, ptr %q) {39; CHECK-LABEL: define i1 @test3(40; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]], ptr [[Q:%.*]]) {41; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 3142; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 143; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[Q]], align 144; CHECK-NEXT: ret i1 false45;46 %lobit = lshr i32 %i, 3147 %t = trunc nuw i32 %lobit to i148 %b = icmp slt i32 %i, 049 %not = xor i1 %t, true50 %op = select i1 %not, i1 %b, i1 false51 store i32 %lobit, ptr %p, align 152 store i32 %lobit, ptr %q, align 153 ret i1 %op54}55 56; Negative Test57define i1 @test4(i32 %i, ptr %p) {58; CHECK-LABEL: define i1 @test4(59; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {60; CHECK-NEXT: [[DOTLOBIT:%.*]] = lshr i32 [[I]], 3061; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[DOTLOBIT]] to i162; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[I]], 063; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[T]], true64; CHECK-NEXT: [[COMMON_RET1_OP:%.*]] = select i1 [[NOT_]], i1 [[B]], i1 false65; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 166; CHECK-NEXT: ret i1 [[COMMON_RET1_OP]]67;68 %lobit = lshr i32 %i, 30 ; should not fold as no. of bits shifted < BitWidth - 169 %t = trunc nuw i32 %lobit to i170 %b = icmp slt i32 %i, 071 %not = xor i1 %t, true72 %op = select i1 %not, i1 %b, i1 false73 store i32 %lobit, ptr %p, align 174 ret i1 %op75}76 77; Negative Test78define i1 @test5(i32 %i, ptr %p) {79; CHECK-LABEL: define i1 @test5(80; CHECK-SAME: i32 [[I:%.*]], ptr [[P:%.*]]) {81; CHECK-NEXT: [[DOTLOBIT:%.*]] = ashr i32 [[I]], 3082; CHECK-NEXT: [[T:%.*]] = trunc nuw i32 [[DOTLOBIT]] to i183; CHECK-NEXT: [[B:%.*]] = icmp slt i32 [[I]], 084; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[T]], true85; CHECK-NEXT: [[COMMON_RET1_OP:%.*]] = select i1 [[NOT_]], i1 [[B]], i1 false86; CHECK-NEXT: store i32 [[DOTLOBIT]], ptr [[P]], align 187; CHECK-NEXT: ret i1 [[COMMON_RET1_OP]]88;89 %lobit = ashr i32 %i, 30 ; should not fold as no. of bits shifted < BitWidth - 190 %t = trunc nuw i32 %lobit to i191 %b = icmp slt i32 %i, 092 %not = xor i1 %t, true93 %op = select i1 %not, i1 %b, i1 false94 store i32 %lobit, ptr %p, align 195 ret i1 %op96}97 98define i1 @fold_lshr_power_of_2(i8 %x) {99; CHECK-LABEL: define i1 @fold_lshr_power_of_2(100; CHECK-SAME: i8 [[X:%.*]]) {101; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4102; CHECK-NEXT: ret i1 [[TRUNC]]103;104 %lshr = lshr i8 16, %x ; 16 is a power of 2105 %trunc = trunc i8 %lshr to i1106 ret i1 %trunc107}108 109define i1 @fold_lshr_power_of_2_minus_1(i8 %x) {110; CHECK-LABEL: define i1 @fold_lshr_power_of_2_minus_1(111; CHECK-SAME: i8 [[X:%.*]]) {112; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4113; CHECK-NEXT: ret i1 [[TRUNC]]114;115 %lshr = lshr i8 15, %x116 %trunc = trunc i8 %lshr to i1117 ret i1 %trunc118}119 120define i1 @fold_ashr_power_of_2(i8 %x) {121; CHECK-LABEL: define i1 @fold_ashr_power_of_2(122; CHECK-SAME: i8 [[X:%.*]]) {123; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4124; CHECK-NEXT: ret i1 [[TRUNC]]125;126 %ashr = ashr i8 16, %x127 %trunc = trunc i8 %ashr to i1128 ret i1 %trunc129}130 131define i1 @fold_ashr_power_of_2_minus_1(i8 %x) {132; CHECK-LABEL: define i1 @fold_ashr_power_of_2_minus_1(133; CHECK-SAME: i8 [[X:%.*]]) {134; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4135; CHECK-NEXT: ret i1 [[TRUNC]]136;137 %ashr = ashr i8 15, %x ; (15 + 1) is a power of 2138 %trunc = trunc i8 %ashr to i1139 ret i1 %trunc140}141 142define i1 @fold_lshr_power_of_2_multi_use(i8 %x) {143; CHECK-LABEL: define i1 @fold_lshr_power_of_2_multi_use(144; CHECK-SAME: i8 [[X:%.*]]) {145; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 16, [[X]]146; CHECK-NEXT: call void @use(i8 [[LSHR]])147; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4148; CHECK-NEXT: ret i1 [[TRUNC]]149;150 %lshr = lshr i8 16, %x ; 16 is a power of 2151 call void @use(i8 %lshr)152 %trunc = trunc i8 %lshr to i1153 ret i1 %trunc154}155 156define i1 @fold_lshr_power_of_2_minus_1_multi_use(i8 %x) {157; CHECK-LABEL: define i1 @fold_lshr_power_of_2_minus_1_multi_use(158; CHECK-SAME: i8 [[X:%.*]]) {159; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 15, [[X]]160; CHECK-NEXT: call void @use(i8 [[LSHR]])161; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4162; CHECK-NEXT: ret i1 [[TRUNC]]163;164 %lshr = lshr i8 15, %x165 call void @use(i8 %lshr)166 %trunc = trunc i8 %lshr to i1167 ret i1 %trunc168}169 170define i1 @fold_ashr_power_of_2_multi_use(i8 %x) {171; CHECK-LABEL: define i1 @fold_ashr_power_of_2_multi_use(172; CHECK-SAME: i8 [[X:%.*]]) {173; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 16, [[X]]174; CHECK-NEXT: call void @use(i8 [[ASHR]])175; CHECK-NEXT: [[TRUNC:%.*]] = icmp eq i8 [[X]], 4176; CHECK-NEXT: ret i1 [[TRUNC]]177;178 %ashr = ashr i8 16, %x179 call void @use(i8 %ashr)180 %trunc = trunc i8 %ashr to i1181 ret i1 %trunc182}183 184define i1 @fold_ashr_power_of_2_minus_1_multi_use(i8 %x) {185; CHECK-LABEL: define i1 @fold_ashr_power_of_2_minus_1_multi_use(186; CHECK-SAME: i8 [[X:%.*]]) {187; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 15, [[X]]188; CHECK-NEXT: call void @use(i8 [[ASHR]])189; CHECK-NEXT: [[TRUNC:%.*]] = icmp ult i8 [[X]], 4190; CHECK-NEXT: ret i1 [[TRUNC]]191;192 %ashr = ashr i8 15, %x ; (15 + 1) is a power of 2193 call void @use(i8 %ashr)194 %trunc = trunc i8 %ashr to i1195 ret i1 %trunc196}197 198define i1 @negative_test_fold_lshr(i8 %x) {199; CHECK-LABEL: define i1 @negative_test_fold_lshr(200; CHECK-SAME: i8 [[X:%.*]]) {201; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 9, [[X]]202; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[LSHR]] to i1203; CHECK-NEXT: ret i1 [[TRUNC]]204;205 %lshr = lshr i8 9, %x ; 9 or (9 + 1) is not a power of 2206 %trunc = trunc i8 %lshr to i1207 ret i1 %trunc208}209 210; Negative Test for arithmetic shift right211define i1 @negative_test_fold_ashr(i8 %x) {212; CHECK-LABEL: define i1 @negative_test_fold_ashr(213; CHECK-SAME: i8 [[X:%.*]]) {214; CHECK-NEXT: [[ASHR:%.*]] = lshr i8 9, [[X]]215; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[ASHR]] to i1216; CHECK-NEXT: ret i1 [[TRUNC]]217;218 %ashr = ashr i8 9, %x ; 9 or (9 + 1) is not a power of 2219 %trunc = trunc i8 %ashr to i1220 ret i1 %trunc221}222 223define i1 @fold_lshr_negated_power_of_2(i8 %x) {224; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2(225; CHECK-SAME: i8 [[X:%.*]]) {226; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3227; CHECK-NEXT: ret i1 [[TRUNC]]228;229 %lshr = lshr i8 -16, %x230 %trunc = trunc i8 %lshr to i1231 ret i1 %trunc232}233 234define i1 @fold_ashr_negated_power_of_2(i8 %x) {235; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2(236; CHECK-SAME: i8 [[X:%.*]]) {237; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3238; CHECK-NEXT: ret i1 [[TRUNC]]239;240 %ashr = ashr i8 -16, %x241 %trunc = trunc i8 %ashr to i1242 ret i1 %trunc243}244 245define i1 @fold_lshr_negated_power_of_2_multi_use(i8 %x) {246; CHECK-LABEL: define i1 @fold_lshr_negated_power_of_2_multi_use(247; CHECK-SAME: i8 [[X:%.*]]) {248; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -16, [[X]]249; CHECK-NEXT: call void @use(i8 [[LSHR]])250; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3251; CHECK-NEXT: ret i1 [[TRUNC]]252;253 %lshr = lshr i8 -16, %x254 call void @use(i8 %lshr)255 %trunc = trunc i8 %lshr to i1256 ret i1 %trunc257}258 259define i1 @fold_ashr_negated_power_of_2_multi_use(i8 %x) {260; CHECK-LABEL: define i1 @fold_ashr_negated_power_of_2_multi_use(261; CHECK-SAME: i8 [[X:%.*]]) {262; CHECK-NEXT: [[ASHR:%.*]] = ashr i8 -16, [[X]]263; CHECK-NEXT: call void @use(i8 [[ASHR]])264; CHECK-NEXT: [[TRUNC:%.*]] = icmp ugt i8 [[X]], 3265; CHECK-NEXT: ret i1 [[TRUNC]]266;267 %ashr = ashr i8 -16, %x268 call void @use(i8 %ashr)269 %trunc = trunc i8 %ashr to i1270 ret i1 %trunc271}272 273define i1 @negative_test_fold_lshr_negated_power_of_2(i8 %x) {274; CHECK-LABEL: define i1 @negative_test_fold_lshr_negated_power_of_2(275; CHECK-SAME: i8 [[X:%.*]]) {276; CHECK-NEXT: [[LSHR:%.*]] = lshr i8 -17, [[X]]277; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[LSHR]] to i1278; CHECK-NEXT: ret i1 [[TRUNC]]279;280 %lshr = lshr i8 -17, %x281 %trunc = trunc i8 %lshr to i1282 ret i1 %trunc283}284 285define i1 @negative_test_fold_ashr_negated_power_of_2(i8 %x) {286; CHECK-LABEL: define i1 @negative_test_fold_ashr_negated_power_of_2(287; CHECK-SAME: i8 [[X:%.*]]) {288; CHECK-NEXT: [[ASHR1:%.*]] = lshr i8 -17, [[X]]289; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[ASHR1]] to i1290; CHECK-NEXT: ret i1 [[TRUNC]]291;292 %ashr = ashr i8 -17, %x293 %trunc = trunc i8 %ashr to i1294 ret i1 %trunc295}296