1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i32 @test_or_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 5; CHECK-LABEL: define i32 @test_or_fshl( 6; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 7; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], [[C]] 8; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[D]] 9; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]]) 10; CHECK-NEXT: ret i32 [[RET]] 11; 12 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 13 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh) 14 %ret = or i32 %val1, %val2 15 ret i32 %ret 16} 17define i32 @test_and_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 18; CHECK-LABEL: define i32 @test_and_fshl( 19; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 20; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A]], [[C]] 21; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[B]], [[D]] 22; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]]) 23; CHECK-NEXT: ret i32 [[RET]] 24; 25 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 26 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh) 27 %ret = and i32 %val1, %val2 28 ret i32 %ret 29} 30define i32 @test_xor_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 31; CHECK-LABEL: define i32 @test_xor_fshl( 32; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 33; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[C]] 34; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[B]], [[D]] 35; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]]) 36; CHECK-NEXT: ret i32 [[RET]] 37; 38 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 39 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh) 40 %ret = xor i32 %val1, %val2 41 ret i32 %ret 42} 43define i32 @test_or_fshr(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 44; CHECK-LABEL: define i32 @test_or_fshr( 45; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 46; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], [[C]] 47; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[D]] 48; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP1]], i32 [[TMP2]], i32 [[SH]]) 49; CHECK-NEXT: ret i32 [[RET]] 50; 51 %val1 = call i32 @llvm.fshr.i32(i32 %a, i32 %b, i32 %sh) 52 %val2 = call i32 @llvm.fshr.i32(i32 %c, i32 %d, i32 %sh) 53 %ret = or i32 %val1, %val2 54 ret i32 %ret 55} 56define i32 @test_or_fshl_cascade(i32 %a, i32 %b, i32 %c) { 57; CHECK-LABEL: define i32 @test_or_fshl_cascade( 58; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]]) { 59; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], [[B]] 60; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[A]], [[B]] 61; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP1]], [[C]] 62; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[C]] 63; CHECK-NEXT: [[OR2:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP3]], i32 [[TMP4]], i32 24) 64; CHECK-NEXT: ret i32 [[OR2]] 65; 66 %fshl1 = call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 24) 67 %fshl2 = call i32 @llvm.fshl.i32(i32 %b, i32 %b, i32 24) 68 %fshl3 = call i32 @llvm.fshl.i32(i32 %c, i32 %c, i32 24) 69 %or1 = or i32 %fshl1, %fshl2 70 %or2 = or i32 %or1, %fshl3 71 ret i32 %or2 72} 73define i32 @test_or_bitreverse(i32 %a, i32 %b) { 74; CHECK-LABEL: define i32 @test_or_bitreverse( 75; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 76; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], [[B]] 77; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[TMP1]]) 78; CHECK-NEXT: ret i32 [[RET]] 79; 80 %val1 = call i32 @llvm.bitreverse.i32(i32 %a) 81 %val2 = call i32 @llvm.bitreverse.i32(i32 %b) 82 %ret = or i32 %val1, %val2 83 ret i32 %ret 84} 85define i32 @test_or_bitreverse_constant(i32 %a, i32 %b) { 86; CHECK-LABEL: define i32 @test_or_bitreverse_constant( 87; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 88; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], 255 89; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[TMP1]]) 90; CHECK-NEXT: ret i32 [[RET]] 91; 92 %val1 = call i32 @llvm.bitreverse.i32(i32 %a) 93 %ret = or i32 %val1, 4278190080 94 ret i32 %ret 95} 96define i32 @test_or_bswap(i32 %a, i32 %b) { 97; CHECK-LABEL: define i32 @test_or_bswap( 98; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 99; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], [[B]] 100; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]]) 101; CHECK-NEXT: ret i32 [[RET]] 102; 103 %val1 = call i32 @llvm.bswap.i32(i32 %a) 104 %val2 = call i32 @llvm.bswap.i32(i32 %b) 105 %ret = or i32 %val1, %val2 106 ret i32 %ret 107} 108define i32 @test_or_bswap_constant(i32 %a, i32 %b) { 109; CHECK-LABEL: define i32 @test_or_bswap_constant( 110; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 111; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A]], 255 112; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[TMP1]]) 113; CHECK-NEXT: ret i32 [[RET]] 114; 115 %val1 = call i32 @llvm.bswap.i32(i32 %a) 116 %ret = or i32 %val1, 4278190080 117 ret i32 %ret 118} 119 120; Negative tests 121 122define i32 @test_or_fshl_fshr(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 123; CHECK-LABEL: define i32 @test_or_fshl_fshr( 124; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 125; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]]) 126; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.fshr.i32(i32 [[C]], i32 [[D]], i32 [[SH]]) 127; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]] 128; CHECK-NEXT: ret i32 [[RET]] 129; 130 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 131 %val2 = call i32 @llvm.fshr.i32(i32 %c, i32 %d, i32 %sh) 132 %ret = or i32 %val1, %val2 133 ret i32 %ret 134} 135define i32 @test_or_bitreverse_bswap(i32 %a, i32 %b) { 136; CHECK-LABEL: define i32 @test_or_bitreverse_bswap( 137; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 138; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[A]]) 139; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.bswap.i32(i32 [[B]]) 140; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]] 141; CHECK-NEXT: ret i32 [[RET]] 142; 143 %val1 = call i32 @llvm.bitreverse.i32(i32 %a) 144 %val2 = call i32 @llvm.bswap.i32(i32 %b) 145 %ret = or i32 %val1, %val2 146 ret i32 %ret 147} 148define i32 @test_or_fshl_mismatched_shamt(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh1, i32 %sh2) { 149; CHECK-LABEL: define i32 @test_or_fshl_mismatched_shamt( 150; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH1:%.*]], i32 [[SH2:%.*]]) { 151; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH1]]) 152; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH2]]) 153; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]] 154; CHECK-NEXT: ret i32 [[RET]] 155; 156 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh1) 157 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh2) 158 %ret = or i32 %val1, %val2 159 ret i32 %ret 160} 161define i32 @test_add_fshl(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 162; CHECK-LABEL: define i32 @test_add_fshl( 163; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 164; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]]) 165; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH]]) 166; CHECK-NEXT: [[RET:%.*]] = add i32 [[VAL1]], [[VAL2]] 167; CHECK-NEXT: ret i32 [[RET]] 168; 169 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 170 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh) 171 %ret = add i32 %val1, %val2 172 ret i32 %ret 173} 174define i32 @test_or_fshl_multiuse(i32 %a, i32 %b, i32 %c, i32 %d, i32 %sh) { 175; CHECK-LABEL: define i32 @test_or_fshl_multiuse( 176; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]], i32 [[SH:%.*]]) { 177; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]]) 178; CHECK-NEXT: call void @use(i32 [[VAL1]]) 179; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.fshl.i32(i32 [[C]], i32 [[D]], i32 [[SH]]) 180; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]] 181; CHECK-NEXT: ret i32 [[RET]] 182; 183 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 184 call void @use(i32 %val1) 185 %val2 = call i32 @llvm.fshl.i32(i32 %c, i32 %d, i32 %sh) 186 %ret = or i32 %val1, %val2 187 ret i32 %ret 188} 189define i32 @test_or_bitreverse_multiuse(i32 %a, i32 %b) { 190; CHECK-LABEL: define i32 @test_or_bitreverse_multiuse( 191; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { 192; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[A]]) 193; CHECK-NEXT: call void @use(i32 [[VAL1]]) 194; CHECK-NEXT: [[VAL2:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[B]]) 195; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], [[VAL2]] 196; CHECK-NEXT: ret i32 [[RET]] 197; 198 %val1 = call i32 @llvm.bitreverse.i32(i32 %a) 199 call void @use(i32 %val1) 200 %val2 = call i32 @llvm.bitreverse.i32(i32 %b) 201 %ret = or i32 %val1, %val2 202 ret i32 %ret 203} 204define i32 @test_or_fshl_constant(i32 %a, i32 %b, i32 %sh) { 205; CHECK-LABEL: define i32 @test_or_fshl_constant( 206; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i32 [[SH:%.*]]) { 207; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A]], i32 [[B]], i32 [[SH]]) 208; CHECK-NEXT: [[RET:%.*]] = or i32 [[VAL1]], -16777216 209; CHECK-NEXT: ret i32 [[RET]] 210; 211 %val1 = call i32 @llvm.fshl.i32(i32 %a, i32 %b, i32 %sh) 212 %ret = or i32 %val1, 4278190080 213 ret i32 %ret 214} 215 216declare void @use(i32) 217declare i32 @llvm.fshl.i32(i32, i32, i32) 218declare i32 @llvm.fshr.i32(i32, i32, i32) 219declare i32 @llvm.bitreverse.i32(i32) 220declare i32 @llvm.bswap.i32(i32) 221