Skip to content

Commit d2af7d1

Browse files
committed
[GlobalISel] Add known bits and sign-bits handling for G_SPLAT_VECTOR
This forwards the KnownBits / SignBits from the scalar operand through to the vector elements. The value is implicitly truncated if it is larger than the vector element size. The change in GISelValueTracking::computeNumSignBits allows scalable sign-bits using a single element demanded elts, and brings it in line with what is done in ValueTracking and SDAG (and GISelValueTracking::getKnownBits). That was my main reason for adding this opcode, to prevent scalable vector asserts.
1 parent 1001d6a commit d2af7d1

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known,
222222
}
223223
break;
224224
}
225+
case TargetOpcode::G_SPLAT_VECTOR: {
226+
computeKnownBitsImpl(MI.getOperand(1).getReg(), Known, APInt(1, 1),
227+
Depth + 1);
228+
// Implicitly truncate the bits to match the official semantics of
229+
// G_SPLAT_VECTOR.
230+
Known = Known.trunc(BitWidth);
231+
break;
232+
}
225233
case TargetOpcode::COPY:
226234
case TargetOpcode::G_PHI:
227235
case TargetOpcode::PHI: {
@@ -854,6 +862,15 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
854862
}
855863
break;
856864
}
865+
case TargetOpcode::G_SPLAT_VECTOR: {
866+
// Check if the sign bits of source go down as far as the truncated value.
867+
Register Src = MI.getOperand(1).getReg();
868+
unsigned NumSrcSignBits = computeNumSignBits(Src, APInt(1, 1), Depth + 1);
869+
unsigned NumSrcBits = MRI.getType(Src).getSizeInBits();
870+
if (NumSrcSignBits > (NumSrcBits - TyBits))
871+
return NumSrcSignBits - (NumSrcBits - TyBits);
872+
break;
873+
}
857874
case TargetOpcode::G_INTRINSIC:
858875
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
859876
case TargetOpcode::G_INTRINSIC_CONVERGENT:
@@ -889,7 +906,7 @@ unsigned GISelValueTracking::computeNumSignBits(Register R,
889906
unsigned GISelValueTracking::computeNumSignBits(Register R, unsigned Depth) {
890907
LLT Ty = MRI.getType(R);
891908
APInt DemandedElts =
892-
Ty.isVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
909+
Ty.isFixedVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
893910
return computeNumSignBits(R, DemandedElts, Depth);
894911
}
895912

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_givaluetracking_test_checks.py UTC_ARGS: --version 5
2+
# RUN: llc -mtriple aarch64 -mattr=+sve -passes="print<gisel-value-tracking>" %s -o - 2>&1 | FileCheck %s
3+
4+
---
5+
name: Scalable
6+
body: |
7+
bb.1:
8+
; CHECK-LABEL: name: @Scalable
9+
; CHECK-NEXT: %0:_ KnownBits:0000000000001010 SignBits:12
10+
; CHECK-NEXT: %1:_ KnownBits:0000000000001010 SignBits:12
11+
%0:_(s16) = G_CONSTANT i16 10
12+
%1:_(<vscale x 8 x s16>) = G_SPLAT_VECTOR %0(s16)
13+
...
14+
---
15+
name: Scalable_trunc
16+
body: |
17+
bb.1:
18+
; CHECK-LABEL: name: @Scalable_trunc
19+
; CHECK-NEXT: %0:_ KnownBits:00000000000000000000000000001010 SignBits:28
20+
; CHECK-NEXT: %1:_ KnownBits:0000000000001010 SignBits:12
21+
%0:_(s32) = G_CONSTANT i32 10
22+
%1:_(<vscale x 8 x s16>) = G_SPLAT_VECTOR %0(s32)
23+
...
24+
---
25+
name: Scalable_signbits
26+
body: |
27+
bb.1:
28+
; CHECK-LABEL: name: @Scalable_signbits
29+
; CHECK-NEXT: %0:_ KnownBits:???????????????? SignBits:1
30+
; CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:17
31+
; CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:17
32+
%0:_(s16) = COPY $h0
33+
%1:_(s32) = G_SEXT %0(s16)
34+
%2:_(<vscale x 4 x s32>) = G_SPLAT_VECTOR %1(s32)
35+
...

0 commit comments

Comments
 (0)