summaryrefslogtreecommitdiff
path: root/src/jit/gtlist.h
diff options
context:
space:
mode:
authorMichelle McDaniel <adiaaida@gmail.com>2016-09-09 10:44:03 -0700
committerMichelle McDaniel <adiaaida@gmail.com>2016-09-16 13:08:29 -0700
commit5c5e53363fd7ae7228764a006de1b1f158e64a16 (patch)
tree8320293693383101ff3517f746dec39c4130f615 /src/jit/gtlist.h
parent832a7498bf7aff89a70800c5f02517866f93dc1f (diff)
downloadcoreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.tar.gz
coreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.tar.bz2
coreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.zip
Add optimization for shift by CNS_INT
This change adds support for shifting by a GT_CNS_INT without going through a helper. If the shiftOp is a GT_CNS_INT we do several transformations based on the shift amount: If the shift amount is 0, the shift is a nop, so we just put together the hi and lo ops as a GT_LONG. If the shift amount is < 32, we generate a shl/shld pattern, a shr/shrd pattern or a sar/shrd pattern, depending on the oper. The first operand of the shrd/shld is a GT_LONG, which we crack in codegen, using it essentially as two int operands, rather than creating a tri op GenTree node (essentially so that we can have 3 operands, instead of the normal two). If the shift amount is 32, it differs between shifting left and shifting right. For GT_LSH, we move the loOp into the hiResult and set the loResult to 0. For GT_RSZ, we move the hiOp into the loResult, and set the hiResult to 0. For GT_RSH, we move the hiOp into the loResult, and set the hiResult to a 31 bit signed shift of the hiOp to sign extend. If the shift amount is less than 64, but larger than 32: for GT_LSH, the hiResult is a shift of the loOp by shift amount - 32 (the move from lo into hi is the 32 bit shift). We set the loResult to 0. For GT_RSH and GT_RSZ, the loResult is a right shift (signed for GT_RSH) of the hiOp by shift amount - 32. The hiResult is 0 for GT_RSZ, and a 31 bit signed shift of hiOp1 for GT_RSH. If the shift amount is >= 64, we set both hiResult and loResult to 0 for GT_LSH and GT_RSZ, and do a sign extend shift to set hiResult and loResult to the sign of the original hiOp for GT_RSH.
Diffstat (limited to 'src/jit/gtlist.h')
-rw-r--r--src/jit/gtlist.h10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h
index bc2f8f2457..3bf360355b 100644
--- a/src/jit/gtlist.h
+++ b/src/jit/gtlist.h
@@ -179,6 +179,16 @@ GTNODE(MUL_LONG , "*long" ,GenTreeOp ,1,GTK_BINOP) // A
// helper calls. It is similar to GT_MULHI, the difference being that
// GT_MULHI drops the lo part of the result, whereas GT_MUL_LONG keeps
// both parts of the result.
+
+// The following are nodes that specify shifts that take a GT_LONG op1. The GT_LONG
+// contains the hi and lo parts of three operand shift form where one op will be
+// shifted into the other op as part of the operation (LSH_HI will shift
+// the high bits of the lo operand into the high operand as it shifts left. RSH_LO
+// will shift the lo bits of the high operand into the lo operand). LSH_HI
+// represents the high operation of a 64-bit left shift by a constant int, and
+// RSH_LO represents the lo operation of a 64-bit right shift by a constant int.
+GTNODE(LSH_HI , "<<Hi" ,GenTreeOp ,0,GTK_BINOP)
+GTNODE(RSH_LO , ">>Lo" ,GenTreeOp ,0,GTK_BINOP)
#endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
#ifdef FEATURE_SIMD