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: 11 define 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. 36 define void @add_small_imm(i8* %p, i64* %q, i32 %b, i32* %addr) { 37 ; CHECK-LABEL: add_small_imm: 38 entry: 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 56 define 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 73 define 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 90 define 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 106 define 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 115 test2: 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 123 test3: 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 131 test4: 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 139 test5: 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 147 test6: 148 %newval6 = add i32 %val, 5 149 store i32 %newval6, i32* @var_i32 150 ret void 151 152 ret: 153 ret void 154 } 155 ; TODO: adds/subs 156