267 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc -mattr=+wide-arithmetic < %s | FileCheck %s3 4target triple = "wasm32-unknown-unknown"5 6define i128 @add_i128(i128 %a, i128 %b) {7; CHECK-LABEL: add_i128:8; CHECK: .functype add_i128 (i32, i64, i64, i64, i64) -> ()9; CHECK-NEXT: # %bb.0:10; CHECK-NEXT: local.get 111; CHECK-NEXT: local.get 212; CHECK-NEXT: local.get 313; CHECK-NEXT: local.get 414; CHECK-NEXT: i64.add12815; CHECK-NEXT: local.set 316; CHECK-NEXT: local.set 417; CHECK-NEXT: local.get 018; CHECK-NEXT: local.get 319; CHECK-NEXT: i64.store 820; CHECK-NEXT: local.get 021; CHECK-NEXT: local.get 422; CHECK-NEXT: i64.store 023; CHECK-NEXT: # fallthrough-return24 %c = add i128 %a, %b25 ret i128 %c26}27 28define i128 @sub_i128(i128 %a, i128 %b) {29; CHECK-LABEL: sub_i128:30; CHECK: .functype sub_i128 (i32, i64, i64, i64, i64) -> ()31; CHECK-NEXT: # %bb.0:32; CHECK-NEXT: local.get 133; CHECK-NEXT: local.get 234; CHECK-NEXT: local.get 335; CHECK-NEXT: local.get 436; CHECK-NEXT: i64.sub12837; CHECK-NEXT: local.set 338; CHECK-NEXT: local.set 439; CHECK-NEXT: local.get 040; CHECK-NEXT: local.get 341; CHECK-NEXT: i64.store 842; CHECK-NEXT: local.get 043; CHECK-NEXT: local.get 444; CHECK-NEXT: i64.store 045; CHECK-NEXT: # fallthrough-return46 %c = sub i128 %a, %b47 ret i128 %c48}49 50define i128 @mul_i128(i128 %a, i128 %b) {51; CHECK-LABEL: mul_i128:52; CHECK: .functype mul_i128 (i32, i64, i64, i64, i64) -> ()53; CHECK-NEXT: .local i6454; CHECK-NEXT: # %bb.0:55; CHECK-NEXT: local.get 056; CHECK-NEXT: local.get 157; CHECK-NEXT: local.get 358; CHECK-NEXT: i64.mul_wide_u59; CHECK-NEXT: local.set 560; CHECK-NEXT: i64.store 061; CHECK-NEXT: local.get 062; CHECK-NEXT: local.get 563; CHECK-NEXT: local.get 164; CHECK-NEXT: local.get 465; CHECK-NEXT: i64.mul66; CHECK-NEXT: i64.add67; CHECK-NEXT: local.get 268; CHECK-NEXT: local.get 369; CHECK-NEXT: i64.mul70; CHECK-NEXT: i64.add71; CHECK-NEXT: i64.store 872; CHECK-NEXT: # fallthrough-return73 %c = mul i128 %a, %b74 ret i128 %c75}76 77define i128 @i64_mul_wide_s(i64 %a, i64 %b) {78; CHECK-LABEL: i64_mul_wide_s:79; CHECK: .functype i64_mul_wide_s (i32, i64, i64) -> ()80; CHECK-NEXT: # %bb.0:81; CHECK-NEXT: local.get 182; CHECK-NEXT: local.get 283; CHECK-NEXT: i64.mul_wide_s84; CHECK-NEXT: local.set 185; CHECK-NEXT: local.set 286; CHECK-NEXT: local.get 087; CHECK-NEXT: local.get 188; CHECK-NEXT: i64.store 889; CHECK-NEXT: local.get 090; CHECK-NEXT: local.get 291; CHECK-NEXT: i64.store 092; CHECK-NEXT: # fallthrough-return93 %a128 = sext i64 %a to i12894 %b128 = sext i64 %b to i12895 %c = mul i128 %a128, %b12896 ret i128 %c97}98 99define i128 @i64_mul_wide_u(i64 %a, i64 %b) {100; CHECK-LABEL: i64_mul_wide_u:101; CHECK: .functype i64_mul_wide_u (i32, i64, i64) -> ()102; CHECK-NEXT: # %bb.0:103; CHECK-NEXT: local.get 1104; CHECK-NEXT: local.get 2105; CHECK-NEXT: i64.mul_wide_u106; CHECK-NEXT: local.set 1107; CHECK-NEXT: local.set 2108; CHECK-NEXT: local.get 0109; CHECK-NEXT: local.get 1110; CHECK-NEXT: i64.store 8111; CHECK-NEXT: local.get 0112; CHECK-NEXT: local.get 2113; CHECK-NEXT: i64.store 0114; CHECK-NEXT: # fallthrough-return115 %a128 = zext i64 %a to i128116 %b128 = zext i64 %b to i128117 %c = mul i128 %a128, %b128118 ret i128 %c119}120 121define i64 @mul_i128_only_lo(i128 %a, i128 %b) {122; CHECK-LABEL: mul_i128_only_lo:123; CHECK: .functype mul_i128_only_lo (i64, i64, i64, i64) -> (i64)124; CHECK-NEXT: # %bb.0:125; CHECK-NEXT: local.get 0126; CHECK-NEXT: local.get 2127; CHECK-NEXT: i64.mul128; CHECK-NEXT: # fallthrough-return129 %c = mul i128 %a, %b130 %d = trunc i128 %c to i64131 ret i64 %d132}133 134declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64)135declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i64)136 137; This is a codegen test to see the effect of overflowing adds on signed138; integers with wide-arithmetic enabled. At this time it doesn't actually139; generate anything differently than without wide-arithmetic but this has also140; been useful for evaluating the proposal.141define { i64, i1 } @add_wide_s(i64 %a, i64 %b) {142; CHECK-LABEL: add_wide_s:143; CHECK: .functype add_wide_s (i32, i64, i64) -> ()144; CHECK-NEXT: .local i64145; CHECK-NEXT: # %bb.0:146; CHECK-NEXT: local.get 0147; CHECK-NEXT: local.get 1148; CHECK-NEXT: local.get 2149; CHECK-NEXT: i64.add150; CHECK-NEXT: local.tee 3151; CHECK-NEXT: i64.store 0152; CHECK-NEXT: local.get 0153; CHECK-NEXT: local.get 2154; CHECK-NEXT: i64.const 0155; CHECK-NEXT: i64.lt_s156; CHECK-NEXT: local.get 3157; CHECK-NEXT: local.get 1158; CHECK-NEXT: i64.lt_s159; CHECK-NEXT: i32.xor160; CHECK-NEXT: i32.store8 8161; CHECK-NEXT: # fallthrough-return162 %pair = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)163 ret { i64, i1 } %pair164}165 166define { i64, i1 } @add_wide_u(i64 %a, i64 %b) {167; CHECK-LABEL: add_wide_u:168; CHECK: .functype add_wide_u (i32, i64, i64) -> ()169; CHECK-NEXT: # %bb.0:170; CHECK-NEXT: local.get 1171; CHECK-NEXT: i64.const 0172; CHECK-NEXT: local.get 2173; CHECK-NEXT: i64.const 0174; CHECK-NEXT: i64.add128175; CHECK-NEXT: local.set 1176; CHECK-NEXT: local.set 2177; CHECK-NEXT: local.get 0178; CHECK-NEXT: local.get 1179; CHECK-NEXT: i64.store8 8180; CHECK-NEXT: local.get 0181; CHECK-NEXT: local.get 2182; CHECK-NEXT: i64.store 0183; CHECK-NEXT: # fallthrough-return184 %pair = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)185 ret { i64, i1 } %pair186}187 188; This is a model of a hypothetical `i64.add_wide3_u` instruction using LLVM189; intrinsics. In theory this should optimize better (to the equivalent below)190; but it doesn't currently.191define { i64, i64 } @add_wide3_u_via_intrinsics(i64 %a, i64 %b, i64 %c) {192; CHECK-LABEL: add_wide3_u_via_intrinsics:193; CHECK: .functype add_wide3_u_via_intrinsics (i32, i64, i64, i64) -> ()194; CHECK-NEXT: # %bb.0:195; CHECK-NEXT: local.get 0196; CHECK-NEXT: local.get 1197; CHECK-NEXT: i64.const 0198; CHECK-NEXT: local.get 2199; CHECK-NEXT: i64.const 0200; CHECK-NEXT: i64.add128201; CHECK-NEXT: local.set 2202; CHECK-NEXT: i64.const 0203; CHECK-NEXT: local.get 3204; CHECK-NEXT: i64.const 0205; CHECK-NEXT: i64.add128206; CHECK-NEXT: local.set 1207; CHECK-NEXT: i64.store 0208; CHECK-NEXT: local.get 0209; CHECK-NEXT: local.get 2210; CHECK-NEXT: local.get 1211; CHECK-NEXT: i64.add212; CHECK-NEXT: i64.store 8213; CHECK-NEXT: # fallthrough-return214 %pair = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)215 %t0 = extractvalue { i64, i1 } %pair, 0216 %carry1 = extractvalue { i64, i1 } %pair, 1217 218 %pair2 = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 %t0, i64 %c)219 %ret1 = extractvalue { i64, i1 } %pair2, 0220 %carry2 = extractvalue { i64, i1 } %pair2, 1221 222 %carry1_64 = zext i1 %carry1 to i64223 %carry2_64 = zext i1 %carry2 to i64224 %ret2 = add i64 %carry1_64, %carry2_64225 226 %r0 = insertvalue { i64, i64 } poison, i64 %ret1, 0227 %r1 = insertvalue { i64, i64 } %r0, i64 %ret2, 1228 ret { i64, i64 } %r1229}230 231; This is a model of a hypothetical `i64.add_wide3_u` instruction using 128-bit232; integer addition. This optimizes better than the above currently.233define { i64, i64 } @add_wide3_u_via_i128(i64 %a, i64 %b, i64 %c) {234; CHECK-LABEL: add_wide3_u_via_i128:235; CHECK: .functype add_wide3_u_via_i128 (i32, i64, i64, i64) -> ()236; CHECK-NEXT: # %bb.0:237; CHECK-NEXT: local.get 1238; CHECK-NEXT: i64.const 0239; CHECK-NEXT: local.get 2240; CHECK-NEXT: i64.const 0241; CHECK-NEXT: i64.add128242; CHECK-NEXT: local.get 3243; CHECK-NEXT: i64.const 0244; CHECK-NEXT: i64.add128245; CHECK-NEXT: local.set 1246; CHECK-NEXT: local.set 2247; CHECK-NEXT: local.get 0248; CHECK-NEXT: local.get 1249; CHECK-NEXT: i64.store 8250; CHECK-NEXT: local.get 0251; CHECK-NEXT: local.get 2252; CHECK-NEXT: i64.store 0253; CHECK-NEXT: # fallthrough-return254 %a128 = zext i64 %a to i128255 %b128 = zext i64 %b to i128256 %c128 = zext i64 %c to i128257 %t0 = add i128 %a128, %b128258 %t1 = add i128 %t0, %c128259 %result = trunc i128 %t1 to i64260 %t2 = lshr i128 %t1, 64261 %carry = trunc i128 %t2 to i64262 263 %ret0 = insertvalue { i64, i64 } poison, i64 %result, 0264 %ret1 = insertvalue { i64, i64 } %ret0, i64 %carry, 1265 ret { i64, i64 } %ret1266}267