1; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-linux-gnu | FileCheck %s 2 3; Note that this should be refactored (for efficiency if nothing else) 4; when the PCS is implemented so we don't have to worry about the 5; loads and stores. 6 7@var_i32 = global i32 42 8@var_i64 = global i64 0 9 10; Add pure 12-bit immediates: 11define void @add_small() { 12; CHECK-LABEL: add_small: 13 14; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, #4095 15 %val32 = load i32, i32* @var_i32 16 %newval32 = add i32 %val32, 4095 17 store i32 %newval32, i32* @var_i32 18 19; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #52 20 %val64 = load i64, i64* @var_i64 21 %newval64 = add i64 %val64, 52 22 store i64 %newval64, i64* @var_i64 23 24 ret void 25} 26 27; Make sure we grab the imm variant when the register operand 28; can be implicitly zero-extend. 29; We used to generate something horrible like this: 30; wA = ldrb 31; xB = ldimm 12 32; xC = add xB, wA, uxtb 33; whereas this can be achieved with: 34; wA = ldrb 35; xC = add xA, #12 ; <- xA implicitly zero extend wA. 36define void @add_small_imm(i8* %p, i64* %q, i32 %b, i32* %addr) { 37; CHECK-LABEL: add_small_imm: 38entry: 39 40; CHECK: ldrb w[[LOAD32:[0-9]+]], [x0] 41 %t = load i8, i8* %p 42 %promoted = zext i8 %t to i64 43 %zextt = zext i8 %t to i32 44 %add = add nuw i32 %zextt, %b 45 46; CHECK: add [[ADD2:x[0-9]+]], x[[LOAD32]], #12 47 %add2 = add nuw i64 %promoted, 12 48 store i32 %add, i32* %addr 49 50; CHECK: str [[ADD2]], [x1] 51 store i64 %add2, i64* %q 52 ret void 53} 54 55; Add 12-bit immediates, shifted left by 12 bits 56define void @add_med() { 57; CHECK-LABEL: add_med: 58 59; CHECK: add {{w[0-9]+}}, {{w[0-9]+}}, {{#3567, lsl #12|#14610432}} 60 %val32 = load i32, i32* @var_i32 61 %newval32 = add i32 %val32, 14610432 ; =0xdef000 62 store i32 %newval32, i32* @var_i32 63 64; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, {{#4095, lsl #12|#16773120}} 65 %val64 = load i64, i64* @var_i64 66 %newval64 = add i64 %val64, 16773120 ; =0xfff000 67 store i64 %newval64, i64* @var_i64 68 69 ret void 70} 71 72; Subtract 12-bit immediates 73define void @sub_small() { 74; CHECK-LABEL: sub_small: 75 76; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, #4095 77 %val32 = load i32, i32* @var_i32 78 %newval32 = sub i32 %val32, 4095 79 store i32 %newval32, i32* @var_i32 80 81; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, #52 82 %val64 = load i64, i64* @var_i64 83 %newval64 = sub i64 %val64, 52 84 store i64 %newval64, i64* @var_i64 85 86 ret void 87} 88 89; Subtract 12-bit immediates, shifted left by 12 bits 90define void @sub_med() { 91; CHECK-LABEL: sub_med: 92 93; CHECK: sub {{w[0-9]+}}, {{w[0-9]+}}, {{#3567, lsl #12|#14610432}} 94 %val32 = load i32, i32* @var_i32 95 %newval32 = sub i32 %val32, 14610432 ; =0xdef000 96 store i32 %newval32, i32* @var_i32 97 98; CHECK: sub {{x[0-9]+}}, {{x[0-9]+}}, {{#4095, lsl #12|#16773120}} 99 %val64 = load i64, i64* @var_i64 100 %newval64 = sub i64 %val64, 16773120 ; =0xfff000 101 store i64 %newval64, i64* @var_i64 102 103 ret void 104} 105 106define void @testing() { 107; CHECK-LABEL: testing: 108 %val = load i32, i32* @var_i32 109 110; CHECK: cmp {{w[0-9]+}}, #4095 111; CHECK: b.ne [[RET:.?LBB[0-9]+_[0-9]+]] 112 %cmp_pos_small = icmp ne i32 %val, 4095 113 br i1 %cmp_pos_small, label %ret, label %test2 114 115test2: 116; CHECK: cmp {{w[0-9]+}}, {{#3567, lsl #12|#14610432}} 117; CHECK: b.lo [[RET]] 118 %newval2 = add i32 %val, 1 119 store i32 %newval2, i32* @var_i32 120 %cmp_pos_big = icmp ult i32 %val, 14610432 121 br i1 %cmp_pos_big, label %ret, label %test3 122 123test3: 124; CHECK: cmp {{w[0-9]+}}, #123 125; CHECK: b.lt [[RET]] 126 %newval3 = add i32 %val, 2 127 store i32 %newval3, i32* @var_i32 128 %cmp_pos_slt = icmp slt i32 %val, 123 129 br i1 %cmp_pos_slt, label %ret, label %test4 130 131test4: 132; CHECK: cmp {{w[0-9]+}}, #321 133; CHECK: b.gt [[RET]] 134 %newval4 = add i32 %val, 3 135 store i32 %newval4, i32* @var_i32 136 %cmp_pos_sgt = icmp sgt i32 %val, 321 137 br i1 %cmp_pos_sgt, label %ret, label %test5 138 139test5: 140; CHECK: cmn {{w[0-9]+}}, #444 141; CHECK: b.gt [[RET]] 142 %newval5 = add i32 %val, 4 143 store i32 %newval5, i32* @var_i32 144 %cmp_neg_uge = icmp sgt i32 %val, -444 145 br i1 %cmp_neg_uge, label %ret, label %test6 146 147test6: 148 %newval6 = add i32 %val, 5 149 store i32 %newval6, i32* @var_i32 150 ret void 151 152ret: 153 ret void 154} 155; TODO: adds/subs 156