From 708f01b09bcba8d10b61e23827d46c5cb7acde86 Mon Sep 17 00:00:00 2001 From: Dongyan Chen Date: Wed, 10 Dec 2025 22:06:31 +0800 Subject: [PATCH 1/4] [InstCombine] Fold logic of zero-checks to multiplication for MinSize --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 60 +++++++++++++++++++ .../CodeGen/RISCV/fold-zero-check-minsize.ll | 57 ++++++++++++++++++ 2 files changed, 117 insertions(+) mode change 100644 => 100755 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp create mode 100755 llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp old mode 100644 new mode 100755 index 6a99d4e29b64f..7861f0937459d --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -631,6 +631,7 @@ namespace { SDValue foldAddToAvg(SDNode *N, const SDLoc &DL); SDValue foldSubToAvg(SDNode *N, const SDLoc &DL); + SDValue foldLogicSetCCToMul(SDNode *N, const SDLoc &DL); SDValue SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, unsigned HiOp); @@ -6648,6 +6649,59 @@ static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2, return ISD::DELETED_NODE; } +// Fold the following patterns for small integers in -Oz mode. +// (X == 0) || (Y == 0) --> (X * Y) == 0 +// (X != 0) && (Y != 0) --> (X * Y) != 0 +SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { + if (OptLevel == CodeGenOptLevel::None || + !DAG.getMachineFunction().getFunction().hasMinSize()) + return SDValue(); + + unsigned Opcode = N->getOpcode(); + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + ISD::CondCode ExpectedCC; + if (Opcode == ISD::OR) { + ExpectedCC = ISD::SETEQ; + } else if (Opcode == ISD::AND) { + ExpectedCC = ISD::SETNE; + } else { + return SDValue(); + } + + if (N0.getOpcode() != ISD::SETCC || N1.getOpcode() != ISD::SETCC) + return SDValue(); + + SDValue A = N0.getOperand(0); + SDValue B = N1.getOperand(0); + SDValue C0 = N0.getOperand(1); + SDValue C1 = N1.getOperand(1); + ISD::CondCode CC0 = cast(N0.getOperand(2))->get(); + ISD::CondCode CC1 = cast(N1.getOperand(2))->get(); + + if (CC0 != ExpectedCC || CC1 != ExpectedCC || !isNullConstant(C0) || + !isNullConstant(C1) || A.getValueType() != B.getValueType() || + !A.getValueType().isScalarInteger()) + return SDValue(); + + unsigned BitWidth = A.getValueSizeInBits(); + KnownBits KnownA = DAG.computeKnownBits(A); + KnownBits KnownB = DAG.computeKnownBits(B); + + if (KnownA.countMaxActiveBits() + KnownB.countMaxActiveBits() > BitWidth) + return SDValue(); + + SDNodeFlags Flags; + Flags.setNoUnsignedWrap(true); + Flags.setNoSignedWrap(true); + + SDValue Mul = DAG.getNode(ISD::MUL, DL, A.getValueType(), A, B, Flags); + + return DAG.getSetCC(DL, N->getValueType(0), Mul, + DAG.getConstant(0, DL, A.getValueType()), ExpectedCC); +} + static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) { using AndOrSETCCFoldKind = TargetLowering::AndOrSETCCFoldKind; assert( @@ -7555,6 +7609,9 @@ SDValue DAGCombiner::visitAND(SDNode *N) { if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), APInt::getAllOnes(BitWidth))) return DAG.getConstant(0, DL, VT); + if (SDValue R = foldLogicSetCCToMul(N, DL)) + return R; + if (SDValue R = foldAndOrOfSETCC(N, DAG)) return R; @@ -8520,6 +8577,9 @@ SDValue DAGCombiner::visitOR(SDNode *N) { if (N1C && DAG.MaskedValueIsZero(N0, ~N1C->getAPIntValue())) return N1; + if (SDValue R = foldLogicSetCCToMul(N, DL)) + return R; + if (SDValue R = foldAndOrOfSETCC(N, DAG)) return R; diff --git a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll new file mode 100755 index 0000000000000..19fc9fb544fb4 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +define i1 @foldLogicSetCCToMul0(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul0: +; CHECK: # %bb.0: +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: ret +entry: + %cmp1 = icmp eq i16 %a, 0 + %cmp2 = icmp eq i16 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} + +define i1 @foldLogicSetCCToMul1(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul1: +; CHECK: # %bb.0: +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: snez a0, a0 +; CHECK-NEXT: ret +entry: + %cmp1 = icmp ne i16 %a, 0 + %cmp2 = icmp ne i16 %b, 0 + %and = and i1 %cmp1, %cmp2 + ret i1 %and +} + +define i1 @foldLogicSetCCToMul2(i64 %a, i64 %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul2: +; CHECK: # %bb.0: +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret +entry: + %cmp1 = icmp eq i64 %a, 0 + %cmp2 = icmp eq i64 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} + +define i1 @foldLogicSetCCToMul3(i16 zeroext %a, i16 zeroext %b) { +; CHECK-LABEL: foldLogicSetCCToMul3: +; CHECK: # %bb.0: +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret +entry: + %cmp1 = icmp eq i16 %a, 0 + %cmp2 = icmp eq i16 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} \ No newline at end of file From 6c14b48cd35368e00287fa836685d4ae896d89a8 Mon Sep 17 00:00:00 2001 From: Dongyan Chen Date: Thu, 11 Dec 2025 22:13:41 +0800 Subject: [PATCH 2/4] fix and add testcases --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 13 +++-- .../CodeGen/RISCV/fold-zero-check-minsize.ll | 49 +++++++++++++++++-- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 7861f0937459d..bebf58db2f8c6 100755 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6653,8 +6653,7 @@ static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2, // (X == 0) || (Y == 0) --> (X * Y) == 0 // (X != 0) && (Y != 0) --> (X * Y) != 0 SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { - if (OptLevel == CodeGenOptLevel::None || - !DAG.getMachineFunction().getFunction().hasMinSize()) + if (!DAG.getMachineFunction().getFunction().hasMinSize()) return SDValue(); unsigned Opcode = N->getOpcode(); @@ -6680,9 +6679,10 @@ SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { ISD::CondCode CC0 = cast(N0.getOperand(2))->get(); ISD::CondCode CC1 = cast(N1.getOperand(2))->get(); - if (CC0 != ExpectedCC || CC1 != ExpectedCC || !isNullConstant(C0) || - !isNullConstant(C1) || A.getValueType() != B.getValueType() || - !A.getValueType().isScalarInteger()) + if (CC0 != ExpectedCC || CC1 != ExpectedCC || + !A.getValueType().isScalarInteger() || + A.getValueType() != B.getValueType() || !isNullConstant(C0) || + !isNullConstant(C1)) return SDValue(); unsigned BitWidth = A.getValueSizeInBits(); @@ -6698,8 +6698,7 @@ SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { SDValue Mul = DAG.getNode(ISD::MUL, DL, A.getValueType(), A, B, Flags); - return DAG.getSetCC(DL, N->getValueType(0), Mul, - DAG.getConstant(0, DL, A.getValueType()), ExpectedCC); + return DAG.getSetCC(DL, N->getValueType(0), Mul, C0, ExpectedCC); } static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) { diff --git a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll index 19fc9fb544fb4..8ce7dd7f1bf17 100755 --- a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll +++ b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll @@ -1,6 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ -; RUN: | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+m -enable-machine-outliner=never < %s | FileCheck %s define i1 @foldLogicSetCCToMul0(i16 zeroext %a, i16 zeroext %b) minsize { ; CHECK-LABEL: foldLogicSetCCToMul0: @@ -54,4 +53,48 @@ entry: %cmp2 = icmp eq i16 %b, 0 %or = or i1 %cmp1, %cmp2 ret i1 %or -} \ No newline at end of file +} + +define i1 @foldLogicSetCCToMul4(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul4: +; CHECK-NOT: mul +; CHECK: ret +entry: + %cmp1 = icmp eq i16 %a, 0 + %cmp2 = icmp ne i16 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} + +define i1 @foldLogicSetCCToMul5(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul5: +; CHECK-NOT: mul +; CHECK: ret +entry: + %cmp1 = icmp eq i16 %a, 1; + %cmp2 = icmp eq i16 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} + +define i1 @foldLogicSetCCToMul6(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul6: +; CHECK-NOT: mul +; CHECK: ret +entry: + %cmp1 = icmp eq i16 %a, 0; + %cmp2 = icmp eq i16 %b, 1 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} + +define i1 @foldLogicSetCCToMul7(i16 zeroext %a, i32 %b) minsize { +; CHECK-LABEL: foldLogicSetCCToMul7: +; CHECK-NOT: mul +; CHECK: ret +entry: + %cmp1 = icmp eq i16 %a, 0 + %cmp2 = icmp eq i32 %b, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} From 30c6ef9376611428e1575074e42d16061b97ad67 Mon Sep 17 00:00:00 2001 From: Dongyan Chen Date: Fri, 12 Dec 2025 12:32:59 +0800 Subject: [PATCH 3/4] add TLI check and fix testcases --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 5 +- .../CodeGen/RISCV/fold-zero-check-minsize.ll | 49 +++++++++++++++---- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index bebf58db2f8c6..8d8aa0c4ec347 100755 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6685,6 +6685,10 @@ SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { !isNullConstant(C1)) return SDValue(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (!TLI.isOperationLegalOrCustom(ISD::MUL, A.getValueType())) + return SDValue(); + unsigned BitWidth = A.getValueSizeInBits(); KnownBits KnownA = DAG.computeKnownBits(A); KnownBits KnownB = DAG.computeKnownBits(B); @@ -6694,7 +6698,6 @@ SDValue DAGCombiner::foldLogicSetCCToMul(SDNode *N, const SDLoc &DL) { SDNodeFlags Flags; Flags.setNoUnsignedWrap(true); - Flags.setNoSignedWrap(true); SDValue Mul = DAG.getNode(ISD::MUL, DL, A.getValueType(), A, B, Flags); diff --git a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll index 8ce7dd7f1bf17..e974b169f6a8c 100755 --- a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll +++ b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll @@ -57,8 +57,11 @@ entry: define i1 @foldLogicSetCCToMul4(i16 zeroext %a, i16 zeroext %b) minsize { ; CHECK-LABEL: foldLogicSetCCToMul4: -; CHECK-NOT: mul -; CHECK: ret +; CHECK: # %bb.0: +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: snez a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret entry: %cmp1 = icmp eq i16 %a, 0 %cmp2 = icmp ne i16 %b, 0 @@ -68,8 +71,12 @@ entry: define i1 @foldLogicSetCCToMul5(i16 zeroext %a, i16 zeroext %b) minsize { ; CHECK-LABEL: foldLogicSetCCToMul5: -; CHECK-NOT: mul -; CHECK: ret +; CHECK: # %bb.0: +; CHECK-NEXT: addi a0, a0, -1 +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret entry: %cmp1 = icmp eq i16 %a, 1; %cmp2 = icmp eq i16 %b, 0 @@ -79,8 +86,12 @@ entry: define i1 @foldLogicSetCCToMul6(i16 zeroext %a, i16 zeroext %b) minsize { ; CHECK-LABEL: foldLogicSetCCToMul6: -; CHECK-NOT: mul -; CHECK: ret +; CHECK: # %bb.0: +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: addi a1, a1, -1 +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret entry: %cmp1 = icmp eq i16 %a, 0; %cmp2 = icmp eq i16 %b, 1 @@ -88,13 +99,33 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul7(i16 zeroext %a, i32 %b) minsize { +define i1 @foldLogicSetCCToMul7(i16 zeroext %a, i32 signext %b) minsize { ; CHECK-LABEL: foldLogicSetCCToMul7: -; CHECK-NOT: mul -; CHECK: ret +; CHECK: # %bb.0: +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: seqz a1, a1 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: ret entry: %cmp1 = icmp eq i16 %a, 0 %cmp2 = icmp eq i32 %b, 0 %or = or i1 %cmp1, %cmp2 ret i1 %or } + +define i1 @nsw_unsafe_proof(i8 zeroext %a, i8 zeroext %b) minsize { +; CHECK-LABEL: nsw_unsafe_proof: +; CHECK: # %bb.0: +; CHECK-NEXT: andi a0, a0, 15 +; CHECK-NEXT: andi a1, a1, 15 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: ret +entry: + %a.masked = and i8 %a, 15 + %b.masked = and i8 %b, 15 + %cmp1 = icmp eq i8 %a.masked, 0 + %cmp2 = icmp eq i8 %b.masked, 0 + %or = or i1 %cmp1, %cmp2 + ret i1 %or +} From a730b7d40a5faa36ee40508814659c4041225eed Mon Sep 17 00:00:00 2001 From: Dongyan Chen Date: Mon, 15 Dec 2025 10:00:41 +0800 Subject: [PATCH 4/4] fix the name of testcases --- .../CodeGen/RISCV/fold-zero-check-minsize.ll | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll index e974b169f6a8c..65acbce1bb262 100755 --- a/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll +++ b/llvm/test/CodeGen/RISCV/fold-zero-check-minsize.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv64 -mattr=+m -enable-machine-outliner=never < %s | FileCheck %s -define i1 @foldLogicSetCCToMul0(i16 zeroext %a, i16 zeroext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul0: +define i1 @fold_or_eq_zero_i16(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: fold_or_eq_zero_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: mul a0, a0, a1 ; CHECK-NEXT: seqz a0, a0 @@ -14,8 +14,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul1(i16 zeroext %a, i16 zeroext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul1: +define i1 @fold_and_ne_zero_i16(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: fold_and_ne_zero_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: mul a0, a0, a1 ; CHECK-NEXT: snez a0, a0 @@ -27,8 +27,8 @@ entry: ret i1 %and } -define i1 @foldLogicSetCCToMul2(i64 %a, i64 %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul2: +define i1 @negative_fold_potential_overflow_i64(i64 %a, i64 %b) minsize { +; CHECK-LABEL: negative_fold_potential_overflow_i64: ; CHECK: # %bb.0: ; CHECK-NEXT: seqz a0, a0 ; CHECK-NEXT: seqz a1, a1 @@ -41,8 +41,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul3(i16 zeroext %a, i16 zeroext %b) { -; CHECK-LABEL: foldLogicSetCCToMul3: +define i1 @negative_fold_no_minsize(i16 zeroext %a, i16 zeroext %b) { +; CHECK-LABEL: negative_fold_no_minsize: ; CHECK: # %bb.0: ; CHECK-NEXT: seqz a0, a0 ; CHECK-NEXT: seqz a1, a1 @@ -55,8 +55,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul4(i16 zeroext %a, i16 zeroext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul4: +define i1 @negative_fold_mismatched_predicates(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: negative_fold_mismatched_predicates: ; CHECK: # %bb.0: ; CHECK-NEXT: seqz a0, a0 ; CHECK-NEXT: snez a1, a1 @@ -69,8 +69,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul5(i16 zeroext %a, i16 zeroext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul5: +define i1 @negative_fold_lhs_nonzero_constant(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: negative_fold_lhs_nonzero_constant: ; CHECK: # %bb.0: ; CHECK-NEXT: addi a0, a0, -1 ; CHECK-NEXT: seqz a0, a0 @@ -84,8 +84,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul6(i16 zeroext %a, i16 zeroext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul6: +define i1 @negative_fold_rhs_nonzero_constant(i16 zeroext %a, i16 zeroext %b) minsize { +; CHECK-LABEL: negative_fold_rhs_nonzero_constant: ; CHECK: # %bb.0: ; CHECK-NEXT: seqz a0, a0 ; CHECK-NEXT: addi a1, a1, -1 @@ -99,8 +99,8 @@ entry: ret i1 %or } -define i1 @foldLogicSetCCToMul7(i16 zeroext %a, i32 signext %b) minsize { -; CHECK-LABEL: foldLogicSetCCToMul7: +define i1 @negative_fold_type_mismatch(i16 zeroext %a, i32 signext %b) minsize { +; CHECK-LABEL: negative_fold_type_mismatch: ; CHECK: # %bb.0: ; CHECK-NEXT: seqz a0, a0 ; CHECK-NEXT: seqz a1, a1 @@ -113,8 +113,8 @@ entry: ret i1 %or } -define i1 @nsw_unsafe_proof(i8 zeroext %a, i8 zeroext %b) minsize { -; CHECK-LABEL: nsw_unsafe_proof: +define i1 @fold_nsw_unsafe_proof(i8 zeroext %a, i8 zeroext %b) minsize { +; CHECK-LABEL: fold_nsw_unsafe_proof: ; CHECK: # %bb.0: ; CHECK-NEXT: andi a0, a0, 15 ; CHECK-NEXT: andi a1, a1, 15