1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[ARM] Selects SSAT/USAT from correct LLVM IR

LLVM will canonicalize conditional selectors to a different pattern than the old code that was used.
This is updating the function to match the new expected patterns and select SSAT or USAT when successful.
Tests have also been updated to use the new patterns.

Differential Review: https://reviews.llvm.org/D87379
This commit is contained in:
Meera Nakrani 2020-09-14 10:57:41 +00:00
parent c407eba528
commit fa71cd65a0
4 changed files with 123 additions and 160 deletions

View File

@ -4998,16 +4998,6 @@ static bool isLowerSaturate(const SDValue LHS, const SDValue RHS,
((K == RHS && K == TrueVal) || (K == LHS && K == FalseVal)));
}
// Similar to isLowerSaturate(), but checks for upper-saturating conditions.
static bool isUpperSaturate(const SDValue LHS, const SDValue RHS,
const SDValue TrueVal, const SDValue FalseVal,
const ISD::CondCode CC, const SDValue K) {
return (isGTorGE(CC) &&
((K == RHS && K == TrueVal) || (K == LHS && K == FalseVal))) ||
(isLTorLE(CC) &&
((K == LHS && K == TrueVal) || (K == RHS && K == FalseVal)));
}
// Check if two chained conditionals could be converted into SSAT or USAT.
//
// SSAT can replace a set of two conditional selectors that bound a number to an
@ -5019,6 +5009,10 @@ static bool isUpperSaturate(const SDValue LHS, const SDValue RHS,
// x < k ? (x < -k ? -k : x) : k
// etc.
//
// LLVM canonicalizes these to either a min(max()) or a max(min())
// pattern. This function tries to match one of these and will return true
// if successful.
//
// USAT works similarily to SSAT but bounds on the interval [0, k] where k + 1 is
// a power of 2.
//
@ -5026,9 +5020,9 @@ static bool isUpperSaturate(const SDValue LHS, const SDValue RHS,
// Additionally, the variable is returned in parameter V, the constant in K and
// usat is set to true if the conditional represents an unsigned saturation
static bool isSaturatingConditional(const SDValue &Op, SDValue &V,
uint64_t &K, bool &usat) {
SDValue LHS1 = Op.getOperand(0);
SDValue RHS1 = Op.getOperand(1);
uint64_t &K, bool &Usat) {
SDValue V1 = Op.getOperand(0);
SDValue K1 = Op.getOperand(1);
SDValue TrueVal1 = Op.getOperand(2);
SDValue FalseVal1 = Op.getOperand(3);
ISD::CondCode CC1 = cast<CondCodeSDNode>(Op.getOperand(4))->get();
@ -5037,82 +5031,57 @@ static bool isSaturatingConditional(const SDValue &Op, SDValue &V,
if (Op2.getOpcode() != ISD::SELECT_CC)
return false;
SDValue LHS2 = Op2.getOperand(0);
SDValue RHS2 = Op2.getOperand(1);
SDValue V2 = Op2.getOperand(0);
SDValue K2 = Op2.getOperand(1);
SDValue TrueVal2 = Op2.getOperand(2);
SDValue FalseVal2 = Op2.getOperand(3);
ISD::CondCode CC2 = cast<CondCodeSDNode>(Op2.getOperand(4))->get();
// Find out which are the constants and which are the variables
// in each conditional
SDValue *K1 = isa<ConstantSDNode>(LHS1) ? &LHS1 : isa<ConstantSDNode>(RHS1)
? &RHS1
: nullptr;
SDValue *K2 = isa<ConstantSDNode>(LHS2) ? &LHS2 : isa<ConstantSDNode>(RHS2)
? &RHS2
: nullptr;
SDValue K2Tmp = isa<ConstantSDNode>(TrueVal2) ? TrueVal2 : FalseVal2;
SDValue V1Tmp = (K1 && *K1 == LHS1) ? RHS1 : LHS1;
SDValue V2Tmp = (K2 && *K2 == LHS2) ? RHS2 : LHS2;
SDValue V2 = (K2Tmp == TrueVal2) ? FalseVal2 : TrueVal2;
SDValue V1Tmp = V1;
SDValue V2Tmp = V2;
// We must detect cases where the original operations worked with 16- or
// 8-bit values. In such case, V2Tmp != V2 because the comparison operations
// must work with sign-extended values but the select operations return
// the original non-extended value.
SDValue V2TmpReg = V2Tmp;
if (V2Tmp->getOpcode() == ISD::SIGN_EXTEND_INREG)
V2TmpReg = V2Tmp->getOperand(0);
if (V1.getOpcode() == ISD::SIGN_EXTEND_INREG &&
V2.getOpcode() == ISD::SIGN_EXTEND_INREG) {
V1Tmp = V1.getOperand(0);
V2Tmp = V2.getOperand(0);
}
// Check that the registers and the constants have the correct values
// in both conditionals
if (!K1 || !K2 || *K1 == Op2 || *K2 != K2Tmp || V1Tmp != V2Tmp ||
V2TmpReg != V2)
return false;
// Check that the registers and the constants match a max(min()) or min(max())
// pattern
if (V1Tmp == TrueVal1 && V2Tmp == TrueVal2 && K1 == FalseVal1 &&
K2 == FalseVal2 &&
((isGTorGE(CC1) && isLTorLE(CC2)) || (isLTorLE(CC1) && isGTorGE(CC2)))) {
// Figure out which conditional is saturating the lower/upper bound.
const SDValue *LowerCheckOp =
isLowerSaturate(LHS1, RHS1, TrueVal1, FalseVal1, CC1, *K1)
? &Op
: isLowerSaturate(LHS2, RHS2, TrueVal2, FalseVal2, CC2, *K2)
? &Op2
: nullptr;
const SDValue *UpperCheckOp =
isUpperSaturate(LHS1, RHS1, TrueVal1, FalseVal1, CC1, *K1)
? &Op
: isUpperSaturate(LHS2, RHS2, TrueVal2, FalseVal2, CC2, *K2)
? &Op2
: nullptr;
// Check that the constant in the lower-bound check is
// the opposite of the constant in the upper-bound check
// in 1's complement.
if (!isa<ConstantSDNode>(K1) || !isa<ConstantSDNode>(K2))
return false;
if (!UpperCheckOp || !LowerCheckOp || LowerCheckOp == UpperCheckOp)
return false;
int64_t Val1 = cast<ConstantSDNode>(K1)->getSExtValue();
int64_t Val2 = cast<ConstantSDNode>(K2)->getSExtValue();
int64_t PosVal = std::max(Val1, Val2);
int64_t NegVal = std::min(Val1, Val2);
// Check that the constant in the lower-bound check is
// the opposite of the constant in the upper-bound check
// in 1's complement.
int64_t Val1 = cast<ConstantSDNode>(*K1)->getSExtValue();
int64_t Val2 = cast<ConstantSDNode>(*K2)->getSExtValue();
int64_t PosVal = std::max(Val1, Val2);
int64_t NegVal = std::min(Val1, Val2);
if (!((Val1 > Val2 && isLTorLE(CC1)) || (Val1 < Val2 && isLTorLE(CC2))) &&
!isPowerOf2_64(PosVal + 1))
return false;
if (((Val1 > Val2 && UpperCheckOp == &Op) ||
(Val1 < Val2 && UpperCheckOp == &Op2)) &&
isPowerOf2_64(PosVal + 1)) {
// Handle the difference between USAT (unsigned) and SSAT (signed) saturation
// Handle the difference between USAT (unsigned) and SSAT (signed)
// saturation
if (Val1 == ~Val2)
usat = false;
Usat = false;
else if (NegVal == 0)
usat = true;
Usat = true;
else
return false;
V = V2;
K = (uint64_t)PosVal; // At this point, PosVal is guaranteed to be positive
V = V2Tmp;
// At this point, PosVal is guaranteed to be positive
K = (uint64_t) PosVal;
return true;
}
return false;
}

View File

@ -20,10 +20,10 @@ define i32 @sat_base_32bit(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpLow = icmp slt i32 %x, -8388608
%cmpUp = icmp sgt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
%0 = icmp slt i32 %x, 8388607
%saturateUp = select i1 %0, i32 %x, i32 8388607
%1 = icmp sgt i32 %saturateUp, -8388608
%saturateLow = select i1 %1, i32 %saturateUp, i32 -8388608
ret i32 %saturateLow
}
@ -34,10 +34,10 @@ define i16 @sat_base_16bit(i16 %x) #0 {
; V6T2: ssat r0, #12, r0
; V4T-NOT: ssat
entry:
%cmpLow = icmp slt i16 %x, -2048
%cmpUp = icmp sgt i16 %x, 2047
%saturateUp = select i1 %cmpUp, i16 2047, i16 %x
%saturateLow = select i1 %cmpLow, i16 -2048, i16 %saturateUp
%0 = icmp slt i16 %x, 2047
%saturateUp = select i1 %0, i16 %x, i16 2047
%1 = icmp sgt i16 %saturateUp, -2048
%saturateLow = select i1 %1, i16 %saturateUp, i16 -2048
ret i16 %saturateLow
}
@ -48,10 +48,10 @@ define i8 @sat_base_8bit(i8 %x) #0 {
; V6T2: ssat r0, #6, r0
; V4T-NOT: ssat
entry:
%cmpLow = icmp slt i8 %x, -32
%cmpUp = icmp sgt i8 %x, 31
%saturateUp = select i1 %cmpUp, i8 31, i8 %x
%saturateLow = select i1 %cmpLow, i8 -32, i8 %saturateUp
%0 = icmp slt i8 %x, 31
%saturateUp = select i1 %0, i8 %x, i8 31
%1 = icmp sgt i8 %saturateUp, -32
%saturateLow = select i1 %1, i8 %saturateUp, i8 -32
ret i8 %saturateLow
}
@ -67,10 +67,10 @@ define i32 @sat_lower_upper_1(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpLow = icmp slt i32 %x, -8388608
%cmpUp = icmp slt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %saturateUp
%0 = icmp sgt i32 %saturateUp, -8388608
%saturateLow = select i1 %0, i32 %saturateUp, i32 -8388608
ret i32 %saturateLow
}
@ -80,10 +80,10 @@ define i32 @sat_lower_upper_2(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpLow = icmp sgt i32 %x, -8388608
%cmpUp = icmp sgt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
%saturateLow = select i1 %cmpLow, i32 %saturateUp, i32 -8388608
%0 = icmp slt i32 %x, 8388607
%saturateUp = select i1 %0, i32 %x, i32 8388607
%1 = icmp sgt i32 %saturateUp, -8388608
%saturateLow = select i1 %1, i32 %saturateUp, i32 -8388608
ret i32 %saturateLow
}
@ -93,10 +93,10 @@ define i32 @sat_upper_lower_1(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpUp = icmp slt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
%saturateUp = select i1 %cmpUp, i32 %saturateLow, i32 8388607
%0 = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %0, i32 %x, i32 -8388608
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -106,10 +106,10 @@ define i32 @sat_upper_lower_2(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %0, i32 %x, i32 -8388608
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -119,10 +119,10 @@ define i32 @sat_upper_lower_3(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpUp = icmp slt i32 8388607, %x
%cmpLow = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -137,10 +137,10 @@ define i32 @sat_le_ge(i32 %x) #0 {
; V6T2: ssat r0, #24, r0
; V4T-NOT: ssat
entry:
%cmpUp = icmp sle i32 8388607, %x
%cmpLow = icmp sge i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %0, i32 %x, i32 -8388608
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -156,8 +156,8 @@ define i32 @no_sat_missing_lower(i32 %x) #0 {
; CHECK-NOT: ssat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
%0 = icmp slt i32 %x, -8388608
%saturateLow = select i1 %0, i32 %x, i32 -8388608
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
ret i32 %saturateUp
}
@ -169,8 +169,8 @@ define i32 @no_sat_missing_upper(i32 %x) #0 {
; CHECK-NOT: ssat
entry:
%cmpUp = icmp slt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, -8388608
%saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x
%0 = icmp sgt i32 %x, -8388608
%saturateLow = select i1 %0, i32 %x, i32 -8388608
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
ret i32 %saturateUp
}
@ -192,10 +192,10 @@ define i32 @no_sat_incorrect_interval(i32 %x) #0 {
; CHECK-LABEL: no_sat_incorrect_interval:
; CHECK-NOT: ssat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, -19088744
%saturateLow = select i1 %cmpLow, i32 -19088744, i32 %x
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp sgt i32 %x, -19088744
%saturateLow = select i1 %0, i32 %x, i32 -19088744
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}

View File

@ -22,10 +22,10 @@ define i32 @unsigned_sat_base_32bit(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpLow = icmp slt i32 %x, 0
%cmpUp = icmp sgt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
%saturateLow = select i1 %cmpLow, i32 0, i32 %saturateUp
%0 = icmp slt i32 %x, 8388607
%saturateUp = select i1 %0, i32 %x, i32 8388607
%1 = icmp sgt i32 %saturateUp, 0
%saturateLow = select i1 %1, i32 %saturateUp, i32 0
ret i32 %saturateLow
}
@ -37,10 +37,10 @@ define i16 @unsigned_sat_base_16bit(i16 %x) #0 {
; V6T2: usat r0, #11, r0
; V4T-NOT: usat
entry:
%cmpLow = icmp slt i16 %x, 0
%cmpUp = icmp sgt i16 %x, 2047
%saturateUp = select i1 %cmpUp, i16 2047, i16 %x
%saturateLow = select i1 %cmpLow, i16 0, i16 %saturateUp
%0 = icmp slt i16 %x, 2047
%saturateUp = select i1 %0, i16 %x, i16 2047
%1 = icmp sgt i16 %saturateUp, 0
%saturateLow = select i1 %1, i16 %saturateUp, i16 0
ret i16 %saturateLow
}
@ -52,10 +52,10 @@ define i8 @unsigned_sat_base_8bit(i8 %x) #0 {
; V6T2: usat r0, #5, r0
; V4T-NOT: usat
entry:
%cmpLow = icmp slt i8 %x, 0
%cmpUp = icmp sgt i8 %x, 31
%saturateUp = select i1 %cmpUp, i8 31, i8 %x
%saturateLow = select i1 %cmpLow, i8 0, i8 %saturateUp
%0 = icmp slt i8 %x, 31
%saturateUp = select i1 %0, i8 %x, i8 31
%1 = icmp sgt i8 %saturateUp, 0
%saturateLow = select i1 %1, i8 %saturateUp, i8 0
ret i8 %saturateLow
}
@ -71,10 +71,10 @@ define i32 @unsigned_sat_lower_upper_1(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpLow = icmp slt i32 %x, 0
%cmpUp = icmp slt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 %x, i32 8388607
%saturateLow = select i1 %cmpLow, i32 0, i32 %saturateUp
%0 = icmp sgt i32 %saturateUp, 0
%saturateLow = select i1 %0, i32 %saturateUp, i32 0
ret i32 %saturateLow
}
@ -85,10 +85,10 @@ define i32 @unsigned_sat_lower_upper_2(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpLow = icmp sgt i32 %x, 0
%cmpUp = icmp sgt i32 %x, 8388607
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %x
%saturateLow = select i1 %cmpLow, i32 %saturateUp, i32 0
%0 = icmp slt i32 %x, 8388607
%saturateUp = select i1 %0, i32 %x, i32 8388607
%1 = icmp sgt i32 %saturateUp, 0
%saturateLow = select i1 %1, i32 %saturateUp, i32 0
ret i32 %saturateLow
}
@ -99,10 +99,10 @@ define i32 @unsigned_sat_upper_lower_1(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpUp = icmp slt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 0, i32 %x
%saturateUp = select i1 %cmpUp, i32 %saturateLow, i32 8388607
%0 = icmp sgt i32 %x, 0
%saturateLow = select i1 %0, i32 %x, i32 0
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -113,10 +113,10 @@ define i32 @unsigned_sat_upper_lower_2(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 0, i32 %x
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp sgt i32 %x, 0
%saturateLow = select i1 %0, i32 %x, i32 0
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -127,10 +127,10 @@ define i32 @unsigned_sat_upper_lower_3(i32 %x) #0 {
; V6T2: usat r0, #23, r0
; V4T-NOT: usat
entry:
%cmpUp = icmp slt i32 8388607, %x
%cmpLow = icmp sgt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 %x, i32 0
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -145,8 +145,8 @@ define i32 @no_unsigned_sat_missing_lower(i32 %x) #0 {
; CHECK-NOT: usat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp sgt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 0, i32 %x
%0 = icmp slt i32 %x, 0
%saturateLow = select i1 %0, i32 %x, i32 0
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
ret i32 %saturateUp
}
@ -158,8 +158,8 @@ define i32 @no_unsigned_sat_missing_upper(i32 %x) #0 {
; CHECK-NOT: usat
entry:
%cmpUp = icmp slt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 0, i32 %x
%0 = icmp sgt i32 %x, 0
%saturateLow = select i1 %0, i32 %x, i32 0
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
ret i32 %saturateUp
}
@ -169,10 +169,10 @@ define i32 @no_unsigned_sat_incorrect_constant(i32 %x) #0 {
; CHECK-LABEL: no_unsigned_sat_incorrect_constant:
; CHECK-NOT: usat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, 0
%saturateLow = select i1 %cmpLow, i32 -1, i32 %x
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%cmpLow.inv = icmp sgt i32 %x, -1
%saturateLow = select i1 %cmpLow.inv, i32 %x, i32 -1
%0 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %0, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}
@ -181,10 +181,10 @@ define i32 @no_unsigned_sat_incorrect_interval(i32 %x) #0 {
; CHECK-LABEL: no_unsigned_sat_incorrect_interval:
; CHECK-NOT: usat
entry:
%cmpUp = icmp sgt i32 %x, 8388607
%cmpLow = icmp slt i32 %x, -4
%saturateLow = select i1 %cmpLow, i32 -4, i32 %x
%saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow
%0 = icmp sgt i32 %x, -4
%saturateLow = select i1 %0, i32 %x, i32 -4
%1 = icmp slt i32 %saturateLow, 8388607
%saturateUp = select i1 %1, i32 %saturateLow, i32 8388607
ret i32 %saturateUp
}

View File

@ -2240,15 +2240,9 @@ define arm_aapcs_vfpcc void @ssatmul_4_q7(i8* nocapture readonly %pSrcA, i8* noc
; CHECK-NEXT: ldrsb r0, [r12], #1
; CHECK-NEXT: ldrsb r1, [r6], #1
; CHECK-NEXT: muls r0, r1, r0
; CHECK-NEXT: asrs r1, r0, #7
; CHECK-NEXT: cmn.w r1, #128
; CHECK-NEXT: mvn r1, #127
; CHECK-NEXT: it gt
; CHECK-NEXT: asrgt r1, r0, #7
; CHECK-NEXT: cmp r1, #127
; CHECK-NEXT: it ge
; CHECK-NEXT: movge r1, #127
; CHECK-NEXT: strb r1, [r4], #1
; CHECK-NEXT: asrs r0, r0, #7
; CHECK-NEXT: ssat r0, #8, r0
; CHECK-NEXT: strb r0, [r4], #1
; CHECK-NEXT: le lr, .LBB13_7
; CHECK-NEXT: .LBB13_8: @ %for.cond.cleanup
; CHECK-NEXT: pop {r4, r5, r6, pc}