diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -3100,20 +3100,32 @@ bool AArch64DAGToDAGISel::SelectSVEAddSubImm(SDValue N, MVT VT, SDValue &Imm, SDValue &Shift) { if (auto CNode = dyn_cast(N)) { - const int64_t ImmVal = CNode->getZExtValue(); + const int64_t ImmVal = CNode->getSExtValue(); SDLoc DL(N); switch (VT.SimpleTy) { case MVT::i8: + // Can always select i8s, no shift, mask the immediate value to + // deal with sign-extended value from lowering. + Shift = CurDAG->getTargetConstant(0, DL, MVT::i32); + Imm = CurDAG->getTargetConstant(ImmVal & 0xFF, DL, MVT::i32); + return true; + case MVT::i16: + // i16 values get sign-extended to 32-bits during lowering. if ((ImmVal & 0xFF) == ImmVal) { Shift = CurDAG->getTargetConstant(0, DL, MVT::i32); Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32); return true; + } else if ((ImmVal & 0xFF) == 0) { + assert((ImmVal >= -32768) && (ImmVal <= 32512)); + Shift = CurDAG->getTargetConstant(8, DL, MVT::i32); + Imm = CurDAG->getTargetConstant((ImmVal >> 8) & 0xFF, DL, MVT::i32); + return true; } break; - case MVT::i16: case MVT::i32: case MVT::i64: + // Range of immediate won't trigger signedness problems for 32/64b. if ((ImmVal & 0xFF) == ImmVal) { Shift = CurDAG->getTargetConstant(0, DL, MVT::i32); Imm = CurDAG->getTargetConstant(ImmVal, DL, MVT::i32); diff --git a/llvm/test/CodeGen/AArch64/sve-int-imm.ll b/llvm/test/CodeGen/AArch64/sve-int-imm.ll --- a/llvm/test/CodeGen/AArch64/sve-int-imm.ll +++ b/llvm/test/CodeGen/AArch64/sve-int-imm.ll @@ -75,6 +75,26 @@ ret %res } +define @add_i8_signedness( %a) { +; CHECK-LABEL: add_i8_signedness +; CHECK: add z0.b, z0.b, #255 +; CHECK-NEXT: ret + %elt = insertelement undef, i8 255, i32 0 + %splat = shufflevector %elt, undef, zeroinitializer + %res = add %a, %splat + ret %res +} + +define @add_i16_signedness( %a) { +; CHECK-LABEL: add_i16_signedness +; CHECK: add z0.h, z0.h, #65280 +; CHECK-NEXT: ret + %elt = insertelement undef, i16 65280, i32 0 + %splat = shufflevector %elt, undef, zeroinitializer + %res = add %a, %splat + ret %res +} + ; SUBR define @subr_i8_low( %a) { ; CHECK-LABEL: subr_i8_low