Skip to content

Commit 923f6ac

Browse files
authored
[FastISel][AArch64] Compare Instruction Miscompilation Fix (#75993)
When shl is folded in compare instruction, a miscompilation occurs when the CMP instruction is also sign-extended. For the following IR: %op3 = shl i8 %op2, 3 %tmp3 = icmp eq i8 %tmp2, %op3 It used to generate cmp w8, w9, sxtb #3 which means sign extend w9, shift left by 3, and then compare with the value in w8. However, the original intention of the IR would require `%op2` to first shift left before extending the operands in the comparison operation . Moreover, if sign extension is used instead of zero extension, the sample test would miscompile. This PR creates a fix for the issue, more specifically to not fold the left shift into the CMP instruction, and to create a zero-extended value rather than a sign-extended value.
1 parent ed3e007 commit 923f6ac

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,15 +1231,6 @@ unsigned AArch64FastISel::emitAddSub(bool UseAdd, MVT RetVT, const Value *LHS,
12311231
// Only extend the RHS within the instruction if there is a valid extend type.
12321232
if (ExtendType != AArch64_AM::InvalidShiftExtend && RHS->hasOneUse() &&
12331233
isValueAvailable(RHS)) {
1234-
if (const auto *SI = dyn_cast<BinaryOperator>(RHS))
1235-
if (const auto *C = dyn_cast<ConstantInt>(SI->getOperand(1)))
1236-
if ((SI->getOpcode() == Instruction::Shl) && (C->getZExtValue() < 4)) {
1237-
Register RHSReg = getRegForValue(SI->getOperand(0));
1238-
if (!RHSReg)
1239-
return 0;
1240-
return emitAddSub_rx(UseAdd, RetVT, LHSReg, RHSReg, ExtendType,
1241-
C->getZExtValue(), SetFlags, WantResult);
1242-
}
12431234
Register RHSReg = getRegForValue(RHS);
12441235
if (!RHSReg)
12451236
return 0;

llvm/test/CodeGen/AArch64/arm64-fast-isel-icmp.ll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --function icmp_i8_shift_and_cmp --version 4
12
; RUN: llc -O0 -fast-isel -fast-isel-abort=1 -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s
23

34
define i32 @icmp_eq_imm(i32 %a) nounwind ssp {
@@ -257,3 +258,18 @@ entry:
257258
%conv2 = zext i1 %cmp to i32
258259
ret i32 %conv2
259260
}
261+
262+
define i32 @icmp_i8_shift_and_cmp(i8 %a, i8 %b) {
263+
entry:
264+
; CHECK-LABEL: icmp_i8_shift_and_cmp:
265+
; CHECK: ubfiz [[REG1:w[0-9]+]], w0, #3, #5
266+
; CHECK-NEXT: sxtb [[REG0:w[0-9]+]], w1
267+
; CHECK-NEXT: cmp [[REG0]], [[REG1]], sxtb
268+
; CHECK-NEXT: cset [[REG:w[0-9]+]], eq
269+
; CHECK-NEXT: and w0, [[REG]], #0x1
270+
%op = shl i8 %a, 3
271+
%cmp = icmp eq i8 %b, %op
272+
%conv = zext i1 %cmp to i32
273+
ret i32 %conv
274+
}
275+

0 commit comments

Comments
 (0)